JPA会員企業:質問にインピーダンスのミスマッチOneToMany関係
質問
についてJPA-2.0(プロバイダは、Hibernate)との関係および対応する管理Java.しようとしている部門の従業員企業:
@Entity
public class Department {
...
@OneToMany(mappedBy = "department")
private Set<Employee> employees = new HashSet<Employee>();
...
}
@Entity
public class Employee {
...
@ManyToOne(targetEntity = Department.class)
@JoinColumn
private Department department;
...
}
そのなかに石えびが入っていて、Javaとの関係自分自身として、以下のユニット試験:
@Transactional
@Test
public void testBoth() {
Department d = new Department();
Employee e = new Employee();
e.setDepartment(d);
d.getEmployees().add(e);
em.persist(d);
em.persist(e);
assertNotNull(em.find(Employee.class, e.getId()).getDepartment());
assertNotNull(em.find(Department.class, d.getId()).getEmployees());
}
退去する場合は e.setDepartment(d)
または d.getEmployees().add(e)
の主張に失敗します。これまでの方が良さそうですね。になっているのでしょうか?為のデータベース取引に係?
@Test
public void testBoth() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Department d = new Department();
Employee e = new Employee();
e.setDepartment(d);
d.getEmployees().add(e);
em.persist(d);
em.persist(e);
em.getTransaction().commit();
em.close();
em = emf.createEntityManager();
em.getTransaction().begin();
assertNotNull(em.find(Employee.class, e.getId()).getDepartment());
assertNotNull(em.find(Department.class, d.getId()).getEmployees());
em.getTransaction().commit();
em.close();
}
いまだに管理する必要がなくなり双方の関係?ないとも思っていた。この変更
e.setDepartment(d);
//d.getEmployees().add(e);
の主張も成功します。ただし、私ケットを受信したときにのみ、その他の側面:
//e.setDepartment(d);
d.getEmployees().add(e);
の主張に失敗します。なぜですか?ではでは、従業員の所有の関係?変更することはできまと行動による注釈う?又はそれだけでも、"一つの"の"OneToMany"と判断した場合、外部キーのデータベースは?
解決
企業との関係にJPAをして所有する逆です。データベースの更新を決めの状況所有する側となります。お場合 Employee
が所有する側の mappedBy
属性。
から JPA2.0仕様:
2.9者との関係
...
に関する双方向または 一方向.双方向 関係の両方を所有する側 と逆非所有)側に動かします。A 一方向の関係のみ は、の所有です。の所有する側の 関係を判定し更新 の関係のデータベースとして 記 3.2.4.
以下のルールが適用される双方向の関係:
- の逆側の双方向 関係として使いこなせなければならなその所有する 側のmappedBy要素 のOneToOne,OneToMany、ManyToMany アノテーションを期待でのmappedBy要素 を指定する財産分野 に、企ることがありますのであらか 関係です。
- 多くの側面 多/多-one 双方向の関係が必要 の所有する側とのmappedBy 要素を指定することはできませんの ManyToOneのアノテーションを期待で
- のための 一双方向 関係の保有側 に対応する側面が含まれ に対応する外国人。
- のための 多対多の双方向 関係はあ を所有する側となります。
他のヒント
どうなるかはわからない試験が実なものにす 必要 対応の両協会が双方向た。さもないが間違っています。ます。
更新: などの仕様を参考によるaxtavtは正しい主張は、あの設定により双方の双方向協会ない内容に誤りがあり、当協会は民間事業体の持続コンテキスト 壊れた.の JPA wiki書 する役割を担っているようになります:
して双方向の関係でオブジェクトモデルの応用の責任を維持する両方向です。ありません魔法のようにJPAた場合、追加又は削除を片側に集ていなければなりませんの追加と削除からの参照 オブジェクトは腐敗.技術的にはデータベースが更新されない問題を修正している場合、追加と削除からの所有の関係が、そのオブジェクトモデルをするものでなければならない""ずる原因となります。
つまり、 正しい や 安全 方の管理の双方向協会Javaの設定の両側にはリンクが付きます。これは通常を使って守備のリンクの管理方法のようになります:
@Entity
public class Department {
...
@OneToMany(mappedBy = "department")
private Set<Employee> employees = new HashSet<Employee>();
...
public void addToEmployees(Employee employee) {
this.employees.add(employee);
employee.setDepartment(this);
}
}
繰り返しないが間違っています。試験だけでんを打つのデータベースに新しい持続コンテキスト(すなわち非常に特定の状況ではなく、一般的なコードク上で稼働している多くない。
あなただけの前のコンテキストで所有側を更新する場合は、新しい永続コンテキストにおける第二のテストが成功した理由は、持続性プロバイダが明らかに永続化するとき、あなたが同様に逆側を更新しなかったことを知ることができないということです。それが唯一の永続性の目的のために所有している方を気に。あなたは持続性プロバイダから永続オブジェクトを取得するときただし、プロバイダが(それはあまりにも、それらが適切に永続化されたと想定される)適切両側に双方向の関連付けを設定します。ここで多くの人がすでに指摘しているようしかし、それは新たに作成された双方向の関連付けを完了するために持続性プロバイダの責任ではなく、あなたが常に適切にあなたのコード内で双方向の関連付けを維持する必要があります。