web-dev-qa-db-ja.com

Hibernate / JPA ManyToOne対OneToMany

現在、 エンティティアソシエーション に関するHibernateのドキュメントを読んでいますが、いくつかのことを理解するのに少し苦労しています。 ManyToOneOneToManyの関連付けの違いに本質的に関係しています。実際のプロジェクトでそれらを使用しましたが、それらの違いを完全に理解することはできません。私の理解では、テーブル/エンティティが別のManyToOneアソシエーションを持っている場合、アソシエーションは反対側OneToManyからのものでなければなりません。それで、特定のケースに基づいてどれを選択するかをどのように決定し、それがデータベース/クエリ/結果にどのように影響するか?どこにでも良い例がありますか?

追伸:質問の関連性のために、誰かが協会の所有者のポイントと双方向と一方向の協会の違いを説明できると便利だと思います。

39
arjacsoh

OrderとOrderLineがあるとします。 OrderとOrderLineの間で単方向のOneToManyを選択できます(OrderにはOrderLineのコレクションがあります)。または、OrderLineとOrderの間にManyToOneの関連付けを選択することもできます(OrderLineにはOrderへの参照があります)。または、両方を選択することもできます。その場合、関連付けは双方向のOneToMany/ManyToOne関連付けになります。

選択するソリューションは、主に状況と、エンティティ間のカップリングのレベルに依存します。たとえば、ユーザー、会社、プロバイダーがすべて多くのアドレスを持っている場合、それらのすべてとアドレスの間で単方向を持ち、アドレスが所有者を知らないようにすることは理にかなっています。

ユーザーが何千ものメッセージを持つことができるユーザーとメッセージがあるとします。とにかくユーザーのすべてのメッセージを要求することはめったにないので、それをメッセージからユーザーへのManyToOneとしてのみモデル化するのが理にかなっています。 JPQLクエリは関連付けをナビゲートすることでエンティティ間を結合するため、クエリを支援するためにのみ関連付けを双方向にすることができます。

双方向の関連付けでは、オブジェクトのグラフに一貫性がない場合があります。たとえば、Order AにはOrderLineの空のセットがありますが、一部のOrderLineにはOrder Aへの参照があります。JPAは、関連付けの一方の側を常に所有者側、もう一方の側を逆側にすることを強制します。 JPAは逆側を無視します。所有者側は、存在する関係を決定する側です。 OneToMany双方向関連付けでは、所有者側が多側である必要があります。したがって、前の例では、所有者側はOrderLineになり、行にはAへの参照があるため、JPAは行と注文Aの間の関連付けを永続化します。

このような関連付けは、次のようにマッピングされます。

順番に :

@OneToMany(mappedBy = "parentOrder") // mappedBy indicates that this side is the 
   // inverse side, and that the mapping is defined by the attribute parentOrder 
   // at the other side of the association.
private Set<OrderLine> lines;

orderLineで:

@ManyToOne
private Order parentOrder;
55
JB Nizet

また、@ManytoOne側の所有者は、関連付けの保存中にn + 1個のクエリのみを必要とします。ここで、nは関連付けの数です(多くの側)。

一方、@OneToManyを所有者として、親エンティティ(片側)を関連付け(多くの側)に挿入すると、2 * N + 1クエリになります。 1つのクエリは関連付けの挿入用で、他のクエリは関連付けられたエンティティの外部キーの更新用です。

4
userJ