マッピング (簡略化)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="br.com._3988215.model.domain">
<class name="Parent" table="PARENT">
<id name="id">
<generator class="native"/>
</id>
<bag cascade="all,delete-orphan" name="childList">
<key column="PARENT_ID" not-null="false"/>
<one-to-many class="Child"/>
</bag>
</class>
<class name="Child" table="CHILD">
<id name="id" column="CHILD_ID">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
生産する
PARENT
ID
CHILD
CHILD_ID
PARENT_ID
あなたの言ったことによると
子コレクションが親オブジェクトから削除されたことを Hibernate に検出させ、親オブジェクトが更新されたときに子テーブルの行をデータベースから削除できるようにしたいと考えています。
何かのようなもの
Parent parent = session.get(...);
parent.getChildren().clear();
session.update(parent);
親インスタンスがアタッチされているため、正常に機能すると言いました
次に、次のものを見てみましょう (通知Assert.assertNull(second) )
public class WhatYouWantTest {
private static SessionFactory sessionFactory;
private Serializable parentId;
private Serializable firstId;
private Serializable secondId;
@BeforeClass
public static void setUpClass() {
Configuration c = new Configuration();
c.addResource("mapping.hbm.3988215.xml");
sessionFactory = c.configure().buildSessionFactory();
}
@Before
public void setUp() throws Exception {
Parent parent = new Parent();
Child first = new Child();
Child second = new Child();
Session session = sessionFactory.openSession();
session.beginTransaction();
parentId = session.save(parent);
firstId = session.save(first);
secondId = session.save(second);
parent.getChildList().add(first);
parent.getChildList().add(second);
session.getTransaction().commit();
session.close();
}
@Test
public void removed_second_from_parent_remove_second_from_database() {
Parent parent = new Parent();
parent.setId((Integer) parentId);
Child first = new Child();
first.setId((Integer) firstId);
/**
* It simulates the second one has been removed
*/
parent.getChildList().add(first);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.update(parent);
session.getTransaction().commit();
session.close();
session = sessionFactory.openSession();
session.beginTransaction();
Child second = (Child) session.get(Child.class, secondId);
Assert.assertNull(second);
session.getTransaction().commit();
session.close();
}
}
残念ながら、テストはパスしません。あなたにできること???
休止状態の参照は言う
拡張 (または長い) セッション - Hibernate セッションは、データベース トランザクションがコミットされた後に基礎となる JDBC 接続から切断され、新しいクライアント リクエストが発生したときに再接続される場合があります。このパターンは会話ごとのセッションとして知られており、再接続さえ不要になります。自動バージョン管理は、同時変更を分離するために使用され、セッションは通常、自動的にフラッシュされることは許可されていませんが、明示的にフラッシュされます。
免責事項:長時間の会話を使用するシナリオはありません。Java EE ステートフル セッション Bean は長時間実行される会話をサポートします。ただし、そのサポートはJPA(Hibernateではありません)用です
または、子を複合要素として有効にする代替マッピングを作成できます。そのライフサイクルは親オブジェクトに依存するため、複合要素に依存して必要なものを取得できます
Parent を拡張する AlternativeParent という名前のクラスを作成します
public class AlternativeParent extends Parent {}
現在はマッピングされています (プレーンな @Entity ではなく複合要素としての子に注意してください)
<class name="AlternativeParent" table="PARENT">
<id name="id">
<generator class="native"/>
</id>
<bag name="childList" table="CHILD">
<key column="PARENT_ID" not-null="false"/>
<composite-element class="Child">
<property column="CHILD_ID" name="id"/>
</composite-element>
</bag>
</class>
Child クラスに便利な equals メソッドを実装するようになりました
public boolean equals(Object o) {
if (!(o instanceof Child))
return false;
Child other = (Child) o;
// identity equality
// Used by composite elements
if(getId() != null) {
return new EqualsBuilder()
.append(getId(), other.getId())
.isEquals();
} else {
// object equality
}
}
上記のテスト ケースをリファクタリングすると (代わりに AlternativeParent を使用して)
@Test
public void removed_second_from_parent_remove_second_from_database() {
AlternativeParent parent = new AlternativeParent();
parent.setId((Integer) parentId);
Child first = new Child();
first.setId((Integer) firstId);
/**
* It simulates the second one has been removed
*/
parent.getChildList().add(first);
Session session = sessionFactory.openSession();
session.beginTransaction();
session.update(parent);
session.getTransaction().commit();
session.close();
session = sessionFactory.openSession();
session.beginTransaction();
Child second = (Child) session.get(Child.class, secondId);
Assert.assertNull(second);
session.getTransaction().commit();
session.close();
}
緑色のバーが表示されます