AI エージェント向け: ドキュメントインデックスは https://www.mongodb.com/ja-jp/docs/llms.txt で利用できます。すべてのページの markdown バージョンは、いずれかの URL パスに .md を追加することで利用できます。
Docs Menu

エンティティ継承階層のマッピング

このガイドでは、 Hibernetes ORM 拡張機能 を使用してJavaクラス階層をMongoDBコレクションにマッピングする方法を学習します。 Java のサブクラスが親クラスを拡張し、そのフィールドを継承する場合、クラスは階層を形成します。 Hibernetes ORM は、 拡張機能が各クラスを階層に保存する方法を決定する継承戦略を提供します。選択した戦略によって、データが保持されるコレクションと結果として得られるドキュメントの形状が決まります。

Hibernetes ORM 拡張機能は次の継承戦略をサポートしています。

  • 単一テーブル継承: Hibernetes ORM 拡張機能はクラス階層全体を 1 つのコレクションに保存します。

  • マッピングされたスーパークラス: 非エンティティのスーパークラスは、独自のコレクションを持つことなく、各サブクラスにフィールドを提供します。

拡張機能は、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
}

Actorインスタンスまたは Directorインスタンスで persist() メソッドを呼び出すと、拡張機能は対応するドキュメントを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 に設定します。

重要

文字弁別子と整数弁別子には明示的な値が必要

Hibernetes では、文字または整数弁別子の場合、クラスの弁別子の値がクラス名にデフォルトはありません。 discriminatorType を DiscriminatorType.CHAR または DiscriminatorType.INTEGER に設定する場合、ルート エンティティを直接インスタンス化しない場合でも、ルート エンティティと各サブクラスに @DiscriminatorValue アノテーションを追加する必要があります。

moviesコレクションには、Movie 階層内のすべてのクラスのドキュメントが含まれています。これらのクラスのいずれかをクエリすると、 Hibernetes ORM 拡張機能は 弁別子フィールドでフィルタリングし、クエリはそのクラスのドキュメントのみを返します。このフィルターは、クエリするクラスによって異なります。

  • サブクラスをクエリすると、拡張機能は、弁別子がそのサブクラスの弁別子の値と等しいドキュメントと一致します。前述の例で Actor をクエリすると、role が "actor" であるドキュメントのみが一致します。

  • ルートクラスをクエリする場合、拡張機能によってフィルターは追加されません。クエリはコレクション内のすべてのドキュメントを読み取り、各ドキュメントの弁別子の値を使用して正しいクラスのオブジェクトを返します。上記の例で Movie をクエリすると、Actor ドキュメントと Director ドキュメントの両方が返されます。コレクションに、弁別子の値が階層内のクラスにマップされていないドキュメントが含まれている場合、クエリは HibernateException をスローします。

エンティティのクエリについて詳しくは、「 クエリの指定」ガイドを参照してください。

@MappedSuperclassマップされたスーパークラスは、それ自体がエンティティになることなく、サブクラスとフィールドマッピングを共有します。マッピングされたスーパークラスを作成するには、スーパークラスに アノテーションを適用します。マップされたスーパークラスはエンティティではないため、 Hibernetes ORM 拡張機能 はコレクションを作成せず、直接クエリすることはできません。

マッピングされたスーパークラスを拡張する各サブクラスは、独自のコレクションにマップされます。各ドキュメントでは、拡張機能は継承されたフィールドとサブクラス独自のフィールドを最上位フィールドとして保存します。拡張機能は継承されたフィールドをネストしたり、個別に保存したりしません。

次の例では、Genre エンティティと Language エンティティの識別子と名前のマッピングを提供する MovieDetails マッピングされたスーパークラスを定義します。

@MappedSuperclass
public 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" }

Hibernetes ORM 拡張機能は、複数のテーブルにわたって単一のクラス階層を保存する次の Hibernetes ORM 継承戦略をサポートしていません。

  • InheritanceType.JOINED: 各クラスを独自のテーブルに保存し、テーブルを結合してインスタンスを再構築します

  • InheritanceType.TABLE_PER_CLASS: 各具象クラスを独自のテーブルに保存し、テーブルを組み合わせて階層をクエリ

クラスを前述の戦略のいずれかでマッピングすると、拡張機能は FeatureNotSupportedException をスローします。

重要

起動時にエラーが発生する

Hibernetes ORM 拡張機能は、SessionFactoryインスタンスを構築するときに継承戦略を検証します。サポートされていない戦略を使用するアプリケーションは起動できません。

エンティティの作成と埋め込みデータのマッピングの詳細については、「 コレクションを表すエンティティの作成 」ガイドを参照してください。

エンティティを使用してデータベース操作を実行する方法については、 「 CRUD操作の実行 」および「 クエリの指定 」ガイドを参照してください。

Hibernetes ORM 拡張機能がサポートする機能のリストを表示するには、「 機能の互換性 」ページを参照してください。

Hibernetes ORM 継承戦略の詳細については、 Hibernetes ORM ドキュメントの「 継承 」を参照してください。