21.3. ライフサイクルのカスケード
明示的に
save()
をコールするのは面倒ですが、カスケードを使って対処することができます
<set name="children" inverse="true" cascade="all"> <key column="parent_id"/> <one-to-many class="Child"/> </set>
これにより先ほどのコードを以下のように単純化します:
Parent p = (Parent) session.load(Parent.class, pid); Child c = new Child(); p.addChild(c); session.flush();
同様に
Parent
を保存または削除するときに、子を一つずつ反復して扱う必要はありません。以下は p
を削除し、そしてデータベースからその子をすべて削除します。
Parent p = (Parent) session.load(Parent.class, pid); session.delete(p); session.flush();
しかし、以下のコードは:
Parent p = (Parent) session.load(Parent.class, pid); Child c = (Child) p.getChildren().iterator().next(); p.getChildren().remove(c); c.setParent(null); session.flush();
データベースから
c
を削除しません。この場合、 p
へのリンクを削除するのみで、NOT NULL
制約違反を引き起こします。明示的にChild
をdelete()
する必要があります。
Parent p = (Parent) session.load(Parent.class, pid); Child c = (Child) p.getChildren().iterator().next(); p.getChildren().remove(c); session.delete(c); session.flush();
今このケースでは実際に
Child
が親なしでは存在できないようになりました。そのため、コレクションから Child
を取り除く場合、これも削除します。そのためには cascade="all-delete-orphan"
を使わなければなりません。
<set name="children" inverse="true" cascade="all-delete-orphan"> <key column="parent_id"/> <one-to-many class="Child"/> </set>
コレクションのマッピングで
inverse="true"
と指定しても、コレクションの要素の反復によって、依然カスケードが処理されます。そのため、カスケードでオブジェクトを保存、削除、更新する必要がある場合は、それをコレクションに追加しなければなりません。単に setParent()
を呼ぶだけでは不十分です。