🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 21.3\. 级联生命周期(Cascading lifecycle) 需要显式调用`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()`是不够的。