`
lbxhappy
  • 浏览: 302931 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

cascade 与 inverse区别

    博客分类:
  • j2ee
阅读更多

一、cascade
1.概述
相当于sql中的级联更新删除,如数据库中两个表之间设置了参照完整性,并指定了级联更新删除,当其中某个表中的记录被修改或删除时,另一个表也会执行相同的操作.
该属性并不是多对多关系一定要用的,有了它只是让我们在插入或删除对象时更方便一些,只要在cascade的源头上插入或是删除,所有cascade的关系就会被自动的插入或删除.

2.属性值:
none:默认值,告诉Hibernate忽略关系;
save-update:告诉Hibernate在下面这些情况导航关联.
--当事务提交时;
--当对象传给save()或update()方法并保存新初始化的瞬时实例及把更改持久到分离实例时.
delete:告诉Hibernate当对象传给delete()时导航关联并删除持久实例;
all:save-update,delete都关联;
all-delte-orphan:跟all一样,除此之外,Hibernate删除任何已经从关联(如,从集合)删除(不再被引用)的持久实体实例;
delete-orphan:Hibernate将会删除任何已经从关联(如,从集合)删除(不再被引用)的持久实体实例.

3.注意
为了能正确使用cascade,unsaved-value是个很重要的属性,该属性表明了持久化对象的状态:
Hibernate 通过该属性来判断一个对象应该是save还是update,如果某个对象的id是unsaved-value属性的值的话,说明这个对象不是 persistence object(处于持久状态的对象,说白了就是数据库中不存在与该对象相关联的记录),那么当然是执行save(insert)操作;否则的话,说明这个 对象是persistence object(处于持久状态或游离状态的对象,即数据库中已存在),就执行update.
(saveOrUpdate方法用的也是这个机制)


二、inverse
1.概述
set的inverse决定是否把对set的改动反映到数据库中去.

2.属性值
false:默认值,反映;
true:不反映

3.使用情景
<many-to-many>:
如有一个Student,Teacher和TeacherStudent 表,Student和Teacher是多对多关系,这个关系由TeacherStudent来表现.那么什么时候插入或删除TeacherStudent 表中的记录来维护关系呢?在用hibernate时,我们不会显式的对TeacherStudent表做操作,操作是hibernate帮我们做 的.hibernate是看hbm文件中指定的是"谁"维护关系,那个在插入或删除"谁"时,就会触发对关系表的操作(如指定 Student.hbm.xml中的<set>的inverse值为false,则在代码中对student类执行或删除操作时,就会在 TeacherStudent表执行相同的操作),前提是"谁"这个对象已经知道这个关系了(即关系另一头的对象(teacher)已经set或是add 到"谁"这个对象里来了).

<one-to-many>:
在多对多中,在哪端inverse="true"效果差不多(在效率上).
在一对多中, 如果要"一"方维护关系,就会在插入或删除"一"方时去update"多"方的每一个与这个"一"的对象有关系的对象(如city和people是一对 多,如果让city来维护关系时,那么在更新city时就会更新people中的cityid字段,删除某一个city时,就会把people中的与被删 除city关联的记录一并删除).这样一来效率就慢.
如果让"多"方维护关系时就不会有update操作,因为关系就是在"多"方的对象中的,直接插入或删除"多"方对象就行了,不管怎么说,还是让"多"方维护关系更直观一些.

对<one-to-many>而言,改变set,会让hibernate执行一系列的update语句,不会delete/insert数据;
对<many-to-many>而言,改变set,只修改关系表的数据,不会影响many-to-many的另一方.
虽然<one-to-many>和<many-to-many>的数据库操作不一样,但目的都是一个,维护数据的一致性.


4.注意
inverse默认是false,就是关系的两端都维护关系,对其中任一个表操作都会触发对关系表的操作,如将 Student.hbm.xml中的set中用了inverse="true"时,那就代表关系是由另一头维护的(Teacher),此时当插入 Student时,不会操作TeacherStudent表.
当关系的两头都用inverse="true"是不对的,会导致任何操作都不触发对关系表的操作.
当关系的两头都用inverse="false"或default值时,会导致在关系表中插入两次关系.

三、区别
1.定义不同
cascade:定义的是关系两端对象到对象的级联关系;
inverse:定义的是关系和对象的级联关系.

2.使用场合
cascade:对关系标记都有效;
inverse:只对set+one-to-many(或many-to-many)有效,对many-to-one,one-to-one无效.

3.效用
cascade:对集合对象中的一个一个元素起作用,如果集合为空,那么cascade不会引发关联操作;
inverse:对集合对象整体起作用.
示例1:
将集合对象设置为null,school.setStudentSet(null)
inverse导致hibernate执行:update Student set School_ID=null where School_ID=?;
cascade则不会执行对Student表的关联更新,因为集合中没有元素.
示例2:
新增一个school,session.save(school)
inverse导致hibernate执行:
for(school的每一个student)
{
update Student set School_ID=? where Student_ID=?---将学生的school_id改为新school的id
}
cascade导致hibernate执行:
for(school的每一个student)
{
session.save(aStudent);--对学生执行save操作
}
示例3:
改变集合中的部分元素(如新增一个元素)
inverse导致hibernate执行:先判断哪能些元素改变了,对改变的元素执行相应的sql;
cascade导致hibernate执行:总是对集合中的每个元素执行关联操作.

4.起效的时机
cascade:在对主控方操作时,级联发生;
inverse:在flush时(commit会自动执行flust),对session中的所有set,hibernate判断每个set是否有变化,对有变化的set执行相应的sql,执行之前,会有个判断:if(invese==true)return;
可以看出cascade在先,inverse在后

5.构造的sql
inverse:
--对set+one-to-many:hibernate对many方的数据库表执行update语句;
--对set+many-to-many:hibernate对关系表执行insert/update/delete语句,注意不是对many方的数据表而是关系表
cascade:对set都是一致的,不管one-to-many还是many-to-many,都简单地把操作传递到set中的每个元素,所以它总是更新many方的数据库表.


四、建议
只对set+many-to-many设置inverse=false,其他的标记不考虑inverse属性,都设为 inverse=true.对cascade,一般对many-to-one,many-to-many,constrained=true的one- to-one不设置级联删除.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics