web-dev-qa-db-ja.com

JPA:モデル階層の実装-@MappedSuperclassと@Inheritance

Play Framework 1.2.4をPostgreSQLおよびJPAと共に使用しています。モデル階層を持ち、これを行うためのいくつかの代替手段があることを確認したいと思います。

基本クラス(抽象)と、この基本クラスを拡張する2つの具象クラスがあります。具体的なクラスが必要な間は、この基本クラスを永続化したくありません。基本クラスには、プロパティとして別のモデルクラスがあります。つまり、基本クラスには@ManyToOne関係があります。

私の質問は、これを実装する最良の方法は何ですか? @MappedSuperclassまたは@Inheritance戦略でTABLE_PER_CLASSを使用していますか? 事実上同等と思われるため、少し混乱しています。

また、クエリやパフォーマンスの問題について、将来直面する可能性のある懸念もあります。

57
huzeyfe

プロパティ、関連付け、およびメソッドを継承するには、MappedSuperClassを使用する必要があります。

エンティティといくつかのサブエンティティがある場合、エンティティの継承を使用する必要があります。

次の質問に答えることで、どちらが必要かを判断できます。モデルに基本クラスとの関連付けが可能な他のエンティティがありますか?

はいの場合、基本クラスは実際にはエンティティであり、エンティティの継承を使用する必要があります。いいえの場合、基本クラスは実際にはいくつかの無関係なエンティティに共通の属性とメソッドを含むクラスであり、マップされたスーパークラスを使用する必要があります。

例えば:

  • メッセージにはいくつかの種類があります:SMSメッセージ、電子メールメッセージ、または電話メッセージ。また、人はメッセージのリストを持っています。メッセージの種類:この場合、Messageは明らかにエンティティであり、エンティティの継承を使用する必要があります。
  • すべてのドメインオブジェクトに作成日、変更日、IDを持たせることができます。したがって、ベースのAbstractDomainObjectクラスから継承させることができます。ただし、AbstractDomainObjectへの関連付けを持つエンティティはありません。常に、より具体的なエンティティ(顧客、会社など)への関連付けになります。この場合、MappedSuperClassを使用するのが理にかなっています。
120
JB Nizet

この記事 で説明したように、_@MappedSupperclass_は_@Inheritance_アノテーションとは異なります。

_@MappedSuperclass_は、_@MappedSuperclass_アノテーションが付けられたスーパークラスを拡張する子クラスによって宣言されているかのように、基本クラスの永続プロパティを含めるようJPAプロバイダーに指示します。

ただし、データベースの観点からは基本クラスが示されていないため、継承はOOPワールドでのみ表示されます。子クラスエンティティのみに関連付けられたマッピングテーブルがあります。

_@Inheritance_アノテーションは、データベーステーブル構造内でOOP継承モデルを具体化することを目的としています。さらに、_@Inheritance_アノテーションが付けられた基本クラスをクエリできますが、できません。 _@MappedSuperclass_アノテーションが付けられた基本クラスに対してそれを行います。

ここで、 _@Inheritance_ JPAアノテーションを使用する理由は、Strategy Pattern のような動作駆動型パターンを実装するためです。

一方、_@MappedSuperclass_は、共通の基本クラスを使用して、基本的なプロパティ、関連付け、およびエンティティ_@Id_の両方を再利用する方法にすぎません。それでも、_@Embeddable_型を使用してほぼ同じ目標を達成できます。唯一の大きな違いは、_@Id_を使用して_@Embeddable_定義を再利用できないことですが、_@MappedSuperclass_を使用して再利用できます。

13
Vlad Mihalcea