9

次の2つの宣言の違いは正確には何ですか

Bは所有側です

@Entity
class A {
   @Id int id;

   @OneToOne
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne(mappedBy="b")
   A a;
}

Aは所有側です

@Entity
class A {
   @Id int id;

   @OneToOne(mappedBy="a")
   B b;
}

@Entity
class B {
   @Id int id;

   @OneToOne
   A a;
}

これを「通常のSQL」で考えると、2つのテーブルがそれぞれ他のテーブルの外部キーを持っているのと同じだと思います。私が理解していないのは、どのエンティティが所有側であるかを指定することの効果、つまり「mappedBy」プロパティを使用することの効果です。通常のSQLに同等のものがあるとは思わないので、これは実際に何を達成しますか。

4

4 に答える 4

14

JPA 2.0 仕様のセクション 2.9 には、次のように書かれています。

関係は、双方向または単方向の場合があります。双方向の関係には、所有側と逆 (非所有) 側の両方があります。一方向の関係には、所有側しかありません。セクション 3.2.4 で説明されているように、関係の所有側がデータベース内の関係の更新を決定します。

双方向の関係には次のルールが適用されます。

  • 双方向関係の反対側は、 、 、または 注釈のmappedBy 要素を 使用して所有側を参照する必要があります。要素は、関係の所有者であるエンティティ内のプロパティまたはフィールドを指定します。OneToOneOneToManyManyToManymappedBy
  • 1 対多 / 多対 1 の双方向関係の多側は所有側でなければならないため、要素をアノテーションmappedByで指定することはできません。ManyToOne
  • 1 対 1 の双方向関係の場合、所有側は、対応する外部キーを含む側に対応します。
  • 多対多の双方向関係では、いずれかの側が所有側になる場合があります。

セクション 3.2.4 の関連部分は次のとおりです。

永続エンティティの状態は、トランザクションのコミット時にデータベースに同期されます。この同期には、上で指定した永続エンティティとそれらの関係に対する更新をデータベースに書き込むことが含まれます。

管理対象エンティティ間の双方向の関係は、関係の所有側が保持する参照に基づいて永続化されます。所有側で保持されているメモリ内参照と逆側で保持されているメモリ内参照が変更された場合に、これらの参照を互いに一致させておくことは、開発者の責任です。単方向の 1 対 1 および 1 対多の関係の場合、関係のセマンティクスが守られていることを確認するのは開発者の責任です。

リレーションシップの逆側への変更が所有側で適切な更新をもたらすようにすることは特に重要です。これにより、データベースとの同期時に変更が失われないようにすることができます。

于 2012-06-10T12:59:45.503 に答える
6

他の人が指摘したように、あなたの例ではどちらの側が所有側であるかについて間違っています。所有側とは、OO の観点から関係を所有することを意味します。実際には、rdbm を永続化プロバイダーとして使用する場合に、db で生成される方法とは逆になることがよくあります。

通常の状況では、オブジェクト指向モデルにより、どちらの側が所有側であるかが明確になります。たとえば、Order には OrderLines があります。注文を削除すると、すべての注文明細が削除されます。OrderLine を削除しても、Order はまだ存在する権利を持っている可能性があります。したがって、注文は所有側です。

より具体的で優れた例として、どちらの側が所有側であるかの影響については、@JB Nizet の回答を参照してください。

JPA 2.0仕様のセクション2.9によると:

1 対 1 の双方向関係の場合、所有側は、対応する外部キーを含む側に対応します。

しかし、同じセクションには次のものもあります。

さらに、この仕様では、次の代替マッピング戦略のサポートも必要です。結合テーブル マッピングによる対 1 関係。

それが続く同じセクションで少し下に:

セクション 2.10 で説明されているデフォルトのマッピングおよびマッピング戦略を上書きまたはさらに改良するために、追加のマッピング注釈 (たとえば、列およびテーブルのマッピング注釈) を指定できます。一部の実装では、これを利用して、二項 OneToOne の FK をターゲット テーブルに入れることができます。

そのシナリオを解決するためのいくつかの戦略について読むには、次を参照してください

私は確認していませんが、2.1 で最初の引用符が削除されることを期待し、信じています。実際のデータベース構造は、データをエンティティとしてモデル化する方法をできるだけ制限しないようにする必要があるためです。

于 2012-06-10T13:05:18.233 に答える
5

最初の例では、Aテーブルには 2 つの列idb_idがあり、Bテーブルには 1 つの列 がありidます。これがA所有側になります。

2 番目の例Bは所有側です。Bには 2 つの列があり、idとがありa_idます。Aには 1 つの列がありidます。

そして、それが違いです:-)

于 2012-06-10T12:25:44.717 に答える
5

所有側は、関連が存在するかどうかを JPA が認識していると見なす側です。最初の例を使用するとします。所有側は、mappedBy 属性がない側です。したがって、所有側は A であり、B ではありません。

これは、データベースに A と B があり、

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
a.setB(b);

JPA は関連付けを保存します (つまり、テーブル A の結合列に B の ID を格納します)。

しかし、もしそうなら

A a = em.find(A.class, aId);
B b = em.find(B.class, bId);
b.setA(a);

逆側を変更し、所有側を変更するのを忘れたため、データベースでは何も変更されません。

于 2012-06-10T12:41:01.867 に答える