22.3. 级联生命周期(Cascading lifecycle)
优质
小牛编辑
135浏览
2023-12-01
需要显式调用
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
约束,在这个例子中)。你需要显式调用 delete()
来删除 Child
。
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c);
session.delete(c);
session.flush();
在我们的例子中,如果没有父对象,子对象就不应该存在,如果将子对象从 collection 中移除,实际上我们是想删除它。要实现这种要求,就必须使用
cascade="all-delete-orphan"
。
<set name="children" inverse="true" cascade="all-delete-orphan">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set
>
注意:即使在 collection 一方的映射中指定
inverse="true"
,级联仍然是通过遍历 collection 中的元素来处理的。如果你想要通过级联进行子对象的插入、删除、更新操作,就必须把它加到 collection 中,只调用 setParent()
是不够的。