在介绍cascade和inverse之前我们要明确一个问题,这两个xml属性标签,都是定义某个set集合(<set>)或是某个<many-to-one>标签的级联操作和关联维护关系的。因此也只有其做为属性的父类在操作这些属性时,它们才起作用。
cascade
例如:
<class name="Test1" table="Test1" >
<id name="id">
<generator class="increment" />
</id>
<set name="childs" cascade="save-update" inverse="true">
<key column="parentId"></key>
<one-to-many class="Test1" />
</set>
<many-to-one name="parent" column="parentId" class="Test1" />
<property name="name" />
</class>
以下是测试代码
Test1 test3 = new Test1();
test3.setName("test3");
Test1 test1 = (Test1) this.getTemplate().load(Test1.class, 1l);
test1.getChilds().add(test3);
这段代码执行完成后会生成一条insert语句
insert into Test1(id,name,parentId) values(?,?,?)
?=1,?=test3,?=null
为什么会产生一条insert语句,这是因为cascade=save-update的作用,如果主对象修改childs的集合(增或删集合内容,或修改了集合中某个对象的属性),则会相应的产生insert和update语句.如果我们设置cascade=none,还是上面的代码,则不会有这条insert语句生成.
如果cascade=save-update,delete或all,则下列代码将删除id=1,及其下的所有的子对象
Test1 test1 = (Test1) this.getTemplate().load(Test1.class, 1l);
this.getTemplate().delete(test1);
如果cascade=cascade="save-update,delete,delete-orphan",则下列代码将删除id=2的子对象,因为其已不是test1的子对象了(按照delete-orphan规则)
Test1 test1 = (Test1) this.getTemplate().load(Test1.class, 1l);
test1.getChilds().remove(this.getTemplate().load(Test1.class, 2l));
inverse
例如:
<class name="Test1" table="Test1" >
<id name="id">
<generator class="increment" />
</id>
<set name="childs" cascade="save-update" inverse="false" >
<key column="parentId"></key>
<one-to-many class="Test1" />
</set>
<many-to-one name="parent" column="parentId" class="Test1" />
<property name="name" />
</class>
还是上面的java代码,执行完后会生成两条语句
insert into Test1 (parentId, name, id) values (?, ?, ?)
update Test1 set parentId=? where id=?
?1=null,?2=test3,?3=4
?4=1,?5=4
为什么会产生两句sql语句,因为inverse=false的作用,inverse=false的一段,是由主对象来维护关联关系,所以主对象只会修改其子对象的外键字段。
注意:第一条insert语句是cascade=save-update的作用产生的。
第二条update语句是inverse=false作用产生的。两者没有任何关系。
如果还是上面的java代码,我们把inverse=true,则只会生成一条insert语句
insert into Test1(id,name,parentId) values(?,?,?)
?=1,?=test3,?=null
为什么parentId还是被设置为null,因为我们的java代码不对,inverse=true则表示将由子类端(childs)来维护外键关系.
如果我们把java代码修改成这样:
Test1 test3 = new Test1();
test3.setName("test3");
Test1 test1 = (Test1) this.getTemplate().load(Test1.class, 1l);
test1.getChilds().add(test3);
test3.setParent(test1);
会生成insert语句中将明确的会赋值parentId。因为test3.setParent(test1)使test3子对象知道了其父对象是谁.
即然是inverse=true,还有test3.setParent(test1);语句,那我们还要test1.getChilds().add(test3);语句做什么,其应该是没用的语句呀,这里如果你这样想,则忽略的一个问题,上面的代码是被一个hibernate的事务包围,在这段代码只有test1是持久性的,在hibernate事务处理后的清除语句(flush)中将只对持久化被修改的属性生成sql语句,这点很重要.