只有关系标记才有cascade属性
一个操作因级联cascade可能触发多个关联操作前一个操作叫主控操作后一个操作叫关联操作
cascade属性的可能值有
all: 所有情况下均进行关联操作即saveupdate和delete
none: 所有情况下均不进行关联操作这是默认值
saveupdate: 在执行save/update/saveOrUpdate时进行关联操作
delete: 在执行delete 时进行关联操作
alldeleteorphan: 当一个节点在对象图中成为孤儿节点时删除该节点比如在一个一对多的关系中Student包含多个book当在对象关系中删除一个book时此book即成为孤儿节点
级联(cascade)属性的作用
级联指的是当主控方执行操作时关联对象(被动方)是否同步执行同一操作
pojo和它的关系属性的关系就是主控方 被动方的关系如果关系属性是一个set那么被动方就是set中的一个一个元素
比如学校(School)有三个属性地区(Address)校长(TheMaster)和学生(Set元素为Student)
执行sessiondelete(school)时级联决定是否执行sessiondelete(Address)sessiondelete(theMaster)
是否对每个aStudent执行sessiondelete(aStudent)
具体执行什么关联操作是根据主控操作来的
主控操作 关联操作
sessionsaveOrUpdate > sessionsaveOrUpdate (执行saveOrUpdate实际上会执行save或者update)
sessionsave > sessionsaveOrUpdate
sessionudpate > sessionsaveOrUpdate
sessiondelete > sessiondelete
主控操作和关联操作的先后顺序是先保存one再保存many先删除many再删除one先update主控方再update被动方
对于onetoone当其属性constrained=false(默认值)时它可看作onetomany关系
当其属性constrained=true时它可看作manytoone关系
对manytomany它可看作onetomany
比如学校(School)有三个属性地区(Address)校长(TheMaster其constrained=false)和学生(Set 元素为Student)
当执行sessionsave(school)时
实际的执行顺序为sessionsave(Address);
sessionsave(school);
sessionsave(theMaster);
for( 对每一个student ){
sessionsave(aStudent);
}
当执行sessiondelete(school)时
实际的执行顺序为sessiondelete(theMaster);
for( 对每一个student ){
sessiondelete(aStudent);
}
sessiondelete(school);
sessiondelete(Address);
当执行sessionupdate(school)时
实际的执行顺序为sessionupdate(school);
sessionsaveOrUpdate(Address);
sessionsaveOrUpdate(theMaster);
for( 对每一个student ){
sessionsaveOrUpdate(aStudent);
}
注意update操作因级联引发的关联操作为saveOrUpdate操作而不是update操作
saveOrUpdate与update的区别是前者根据操作对象是保存了还是没有保存而决定执行update还是save
extends: 实际中删除学校不会删除地区即地区的cascade一般设为false
另外manytomany关系很少设置cascade=true而是设置inverse=false这个反映了cascade和inverse的区别见
cascade的默认值为false所以inverse属性默认会进行关联更新
总结级联(cascade)就是操作一个对象时对它的属性(其cascade=true)也进行这个操作
inverse和cascade的比较
这两个属性本身互不影响但起的作用有些类似都能引发对关系表的更新
inverse只对set+onetomany(或manytomany)有效对manytoone onetoone无效
cascade对关系标记都有效
inverse对集合对象整体起作用cascade对集合对象中的一个一个元素起作用如果集合为空那么cascade不会引发关联操作
比如将集合对象置为null schoolsetStudentSet(null)
inverse导致hibernate执行:udpate STUDENT set SCHOOL_ID=null where SCHOOL_ID=?
cascade则不会执行对STUDENT表的关联更新 因为集合中没有元素
再比新增一个school sessionsave(school)
inverse导致hibernate执行
for( 对(school的每一个student ){
udpate STUDENT set SCHOOL_ID=? where STUDENT_ID=? //将学生的school_id改为新的school的id
}
cascade导致hibernate执行
for( 对school的每一个student ){
sessionsave(aStudent); //对学生执行save操作
}
extends:如果改变集合中的部分元素(比如新增一个元素)
inverse: hibernate先判断哪些元素改变了对改变的元素执行相应的sql
cascade: 它总是对集合中的每个元素执行关联操作
(在关联操作中hibernate会判断操作的对象是否改变)
两个起作用的时机不同
cascade在对主控方操作时级联发生
inverse: 在flush时(commit会自动执行flush)对session中的所有sethibernate判断每个set是否有变化
对有变化的set执行相应的sql执行之前会有个判断if( inverse == true ) return;
可以看出cascade在先inverse在后
inverse 对set + onetomany 和 set + manytomany 起的作用不同hibernate生成的sql不同
对onetomanyhibernate对many方的数据库表执行update语句
对manytomany hibernate对关系表执行insert/update/delte语句注意不是对many方的数据库表而是关系表
cascase 对set都是一致的不管onetomany还是manytomany都简单地把操作传递到set中的每个元素所以它总是更新many
方的数据库表
建议只对set + manytomany设置inverse=false其他的标记不考虑inverse属性都设为inverse=true
对cascade一般对manytoonemanytomanyconstrained=true的onetoone 不设置级联删除