質問
次の方法で注釈が付けられた2つのエンティティクラスがあります
@Entity
class A {
@ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
private List<B> b;
..
}
@Entity
class B {
@ManyToMany(cascade=CascadeType.ALL)
private List<A> a;
..
}
クラス「B」のインスタンスを保存すると、リレーションはデータベースに保存され、クラス「A」のゲッターは正しいBのサブセットを返します。ただし、「A」のBのリストに変更を加えた場合、その変更はデータベースに保存されませんか?
質問は、どちらのクラスの変更も「カスケード」されるようにする方法です。他のクラスに?
編集:mappedByパラメーターを削除してJoinTable(および列)を定義するさまざまなバリエーションを試しましたが、正しい組み合わせを見つけることができませんでした。
解決
最短の答えはあなたにはできないと思われ、それは理にかなっています。双方向の多対多の関連付けでは、一方がマスターである必要があり、基礎となる結合テーブルへの変更を永続化するために使用されます。 JPAはアソシエーションの両側を維持しないため、データベースに格納されるとリロードできないメモリ状況になる可能性があります。 例:
A a1 = new A();
A a2 = new A();
B b = new B();
a1.getB().add(b);
b.getA().add(a2);
この状態を維持できる場合、結合テーブルに次のエントリが作成されます。
a1_id, b_id
a2_id, b_id
しかし、ロードすると、JPAは、a1ではなくa2についてのみbに通知するつもりだったことをどのように知るのでしょうか?そして、bについて知らないa2についてはどうですか?
このため、双方向の関連付けを自分で維持する必要があり(また、上記の例をメモリ内でも取得できないようにします)、JPAはその片側の状態に基づいてのみ持続します。
他のヒント
逆結合列を指定しましたか?
@Entity
class A {
@ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
private List <B> b;
..
}
@Entity
class B {
@ManyToMany
@JoinTable (
name="A_B",
joinColumns = {@JoinColumn(name="A_ID")},
inverseJoinColumns = {@JoinColumn(name="B_ID")}
)
private List<A> a;
..
}
列A_IDおよびB_IDを持つA_Bという名前の結合テーブルを想定しています。
関係が双方向であるため、アプリケーションが更新されます 関係の一方、他方も更新されるはずです、 同期します。 JPAでは、一般的なJavaと同様に、 維持するアプリケーションまたはオブジェクトモデルの責任 アプリケーションが 関係、それから反対側に追加する必要があります。
これは、オブジェクトモデルのaddまたはsetメソッドを介して解決できます。 リレーションシップの両側を処理するため、アプリケーションコード 心配する必要はありません。これには2つの方法があります。 関係維持コードを片側にのみ追加できます 関係の片方からのみセッターを使用します(例: 反対側を保護する)、または両側に追加して確認する 無限ループを避けます。
そのようにクラスBのAフィールドにmappedByパラメーターを追加しようとしましたか
@Entity
class B {
@ManyToMany(cascade=CascadeType.ALL, mappedBy = "b")
private List<A> a;
..
}
A_Mの答えに小さな間違いがあるかもしれません。 私の意見では:
@Entity class B { @ManyToMany @JoinTable ( name="A_B", joinColumns = {@JoinColumn(name="B_ID")}, inverseJoinColumns = {@JoinColumn(name="A_ID")} ) private List a; .. }