AI 에이전트의 경우: 문서 인덱스는 https://www.mongodb.com/ko-kr/docs/llms.txt에서 사용할 수 있으며, 모든 페이지의 마크다운 버전은 어떤 URL 경로에 .md를 추가하여 사용할 수 있습니다.

엔티티 상속 계층 구조 매핑

이 가이드에서는 Hibernate ORM 확장을 사용하여 Java 클래스 계층 구조를 MongoDB 컬렉션에 매핑하는 방법을 알아봅니다. Java 하위 클래스가 상위 클래스를 확장하고 해당 필드를 상속하면 클래스는 계층 구조를 형성합니다. Hibernate ORM은 확장이 계층 구조의 각 클래스를 저장하는 방법을 결정하는 상속 전략을 제공합니다. 선택한 전략에 따라 데이터가 저장되는 컬렉션과 결과 문서의 형태가 결정됩니다.

Hibernate ORM 확장은 다음 상속 전략을 지원합니다.

  • 단일 테이블 상속: Hibernate ORM 확장은 전체 클래스 계층 구조를 하나의 컬렉션에 저장합니다.

  • 매핑된 슈퍼클래스: 엔티티가 아닌 슈퍼클래스는 자체 컬렉션 없이 각 서브클래스에 필드를 제공합니다.

이 확장 프로그램은 JOINED 및 TABLE_PER_CLASS 상속 전략을 지원하지 않습니다. 자세한 내용은 이 가이드의 지원되지 않는 전략 섹션을 참조하세요.

단일 테이블 상속 전략에서 프레임워크는 계층 구조의 모든 클래스를 동일한 MongoDB 컬렉션에 저장합니다. 이 전략을 사용하려면 계층 구조에서 최상위 부모 클래스인 루트 엔티티에 @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 주석을 적용하세요.

컬렉션에는 여러 클래스에 매핑되는 문서가 포함되어 있으므로, 확장 프로그램은 각 문서가 매핑되는 클래스를 기록해야 합니다. 객체를 저장할 때 확장 프로그램은 이 정보를 판별자 필드에 저장합니다. 컬렉션을 쿼리하면 확장 프로그램이 판별자 값을 읽어 인스턴스화할 클래스를 결정합니다.

차별자 필드를 지정하려면 루트 엔티티에 @DiscriminatorColumn 주석을 적용합니다. 클래스의 차별자 값을 설정하려면 클래스에 @DiscriminatorValue 주석을 적용합니다.

다음 예시는 Movie 계층 구조를 movies 컬렉션에 매핑합니다. Actor 및 Director 하위 클래스는 모두 Movie에서 name 필드를 상속하지만, 각 하위 클래스는 고유한 필드도 추가합니다. 각 문서는 role 판별자 필드에 "actor" 또는 "director"을 저장합니다.

@Entity@Table(name = "movies")@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name = "role")public abstract class Movie { @Id @ObjectIdGenerator private ObjectId id; private String name; // Getter and setter methods } @Entity@DiscriminatorValue("actor")public class Actor extends Movie { private List<String> awards; // Getter and setter methods } @Entity@DiscriminatorValue("director")public class Director extends Movie { private String studio; // Getter and setter methods }

persist() 인스턴스 또는 Actor 인스턴스에서 Director 메서드를 호출하면 확장이 해당 문서를 movies 컬렉션에 삽입합니다. 각 문서에는 해당 클래스가 정의하는 필드와 해당 클래스의 판별자 값이 포함되어 있습니다.

{ "_id": ObjectId("..."), "role": "actor", "name": "Andrew Garfield", "awards": ["Golden Globe Award"] }{ "_id": ObjectId("..."), "role": "director", "name": "Greta Gerwig", "studio": "Warner Bros." }

앞선 예시에서는 기본값 판별자 유형인 string 판별자를 사용합니다. 이 유형을 변경하려면 @DiscriminatorColumn 주석의 discriminatorType 요소를 설정하세요. 판별자를 문자로 저장하려면 이 요소를 DiscriminatorType.CHAR로 설정하고, 정수로 저장하려면 DiscriminatorType.INTEGER으로 설정하세요.

중요

문자 및 정수 판별자에는 명시적 값이 필요합니다

Hibernate는 문자 또는 정수 판별자의 경우 클래스의 판별자 값을 클래스 이름으로 기본 설정하지 않습니다. discriminatorType을(를) DiscriminatorType.CHAR 또는 DiscriminatorType.INTEGER(으)로 설정하는 경우, 루트 엔터티를 직접 인스턴스화하지 않더라도 루트 엔터티와 각 하위 클래스에 @DiscriminatorValue 주석을 추가해야 합니다.

movies 컬렉션에는 Movie 계층 구조의 모든 클래스에 대한 문서가 포함되어 있습니다. 이러한 클래스 중 하나를 쿼리하면 Hibernate ORM 확장이 판별자 필드를 필터링하여 쿼리가 해당 클래스에 대한 문서만 반환하도록 합니다. 이 필터는 쿼리하는 클래스에 따라 다릅니다.

  • 하위 클래스를 쿼리하면 확장은 판별자가 해당 하위 클래스의 판별자 값과 일치하는 문서를 찾습니다. 이전 예시에서 Actor을(를) 쿼리하면 role이(가) "actor"인 문서만 일치합니다.

  • 루트 클래스를 쿼리하는 경우, 확장은 필터를 추가하지 않습니다. 쿼리는 컬렉션의 모든 문서를 읽고 각 문서의 판별자 값을 사용하여 올바른 클래스의 객체를 반환합니다. 앞의 예시에서 Movie을(를) 쿼리하면 Actor 및 Director 문서가 모두 반환됩니다. 컬렉션에 판별자 값이 계층 구조의 클래스에 매핑되지 않는 문서가 포함되어 있으면 쿼리는 HibernateException을(를) 발생시킵니다.

엔티티 쿼리에 대해 자세히 알아보려면 쿼리 지정 가이드를 참조하세요.

매핑된 슈퍼클래스(mapped superclass)는 엔티티 자체가 되지 않고 서브클래스와 필드 매핑을 공유합니다. 매핑된 슈퍼클래스를 생성하려면 슈퍼클래스에 @MappedSuperclass 어노테이션을 적용하세요. 매핑된 슈퍼클래스는 엔티티가 아니므로 Hibernate ORM 확장은 이에 대한 컬렉션을 생성하지 않으며 직접 쿼리할 수 없습니다.

매핑된 슈퍼클래스를 확장하는 각 서브클래스는 자체 컬렉션에 매핑됩니다. 각 문서에서 확장은 상속된 필드와 서브클래스 자체 필드를 최상위 필드로 저장합니다. 확장은 상속된 필드를 중첩하거나 별도로 저장하지 않습니다.

다음 예시는 Genre 엔티티와 Language 엔티티에 대한 식별자와 이름 매핑을 제공하는 MovieDetails 매핑된 슈퍼클래스를 정의합니다.

@MappedSuperclasspublic abstract class MovieDetails { @Id @ObjectIdGenerator private ObjectId id; private String name; // Getter and setter methods } @Entity@Table(name = "genres")public class Genre extends MovieDetails { private String description; // Getter and setter methods } @Entity@Table(name = "languages")public class Language extends MovieDetails { private String code; // Getter and setter methods }

이전 예시에서 @MappedSuperclass 주석을 사용하면 MovieDetails이(가) 엔터티가 되지 않고도 id 및 name 매핑을 정의할 수 있습니다. 그런 다음 Genre 및 Language의 @Entity 및 @Table 주석은 각 하위 클래스를 자체 컬렉션에 매핑합니다.

결과적으로 확장 프로그램은 MovieDetails에 대한 컬렉션을 생성하지 않습니다. 대신 확장 프로그램은 Genre 문서를 genres 컬렉션에 저장하고 Language 문서를 languages 컬렉션에 저장합니다. 각 문서에는 해당 클래스가 정의하는 필드 외에도 MovieDetails이 매핑하는 _id 및 name 필드가 포함되어 있습니다.

{ "_id": ObjectId("..."), "description": "Serious, narrative-driven stories.", "name": "Drama" }{ "_id": ObjectId("..."), "code": "en", "name": "English" }

Hibernate ORM 확장은 여러 테이블에 걸쳐 단일 클래스 계층 구조를 저장하는 다음 Hibernate ORM 상속 전략을 지원하지 않습니다.

  • InheritanceType.JOINED: 각 클래스를 자체 테이블에 저장하고 테이블을 조인하여 인스턴스를 재구성합니다.

  • InheritanceType.TABLE_PER_CLASS: 각 구체 클래스를 자체 테이블에 저장하고 테이블을 결합하여 계층 구조를 쿼리합니다.

이전 전략 중 하나로 클래스를 매핑하면 확장 기능이 FeatureNotSupportedException을(를) 발생시킵니다.

중요

스타트업 시 오류 발생

Hibernate ORM 확장은 SessionFactory 인스턴스를 빌드할 때 상속 전략을 검증합니다. 지원되지 않는 전략을 사용하는 애플리케이션은 시작할 수 없습니다.

엔터티 생성 및 포함된 데이터 매핑에 대한 자세한 내용은 컬렉션을 나타내는 엔터티 생성 가이드를 참조하세요.

엔터티를 사용하여 데이터베이스 작업을 실행하는 방법을 학습하려면 CRUD 작업 수행 및 쿼리 지정 가이드를 참조하세요.

Hibernate ORM 확장이 지원하는 기능 목록을 보려면 기능 호환성 페이지를 참조하세요.

Hibernate ORM 상속 전략에 대해 자세히 학습하려면 Hibernate ORM 문서에서 상속 을 참조하세요.