hibernate中 cascade属性详解

 

 配置关联时,我们考虑两点:程序执行效率和实际业务需要,前面的例子中无论是单向的关联还是双向的关联,我们都要分别对实体类使用session.save()才能将数据保存至数据库。
问题:如果保存数据非常多,那编码是一件恐怖的事情。
有没有简单的方法呢?
将<set>标签cascade=all
总结:我们只对district对象执行了持久化操作,但是通过sql语句,我们发现street执行了持久啊操作,这就是cascade属性的作用。当设置cascade属性不none时,Hibernate会持久化所关联的对象。


1.all   :对象所有操作进行级联操作  save,update,delete
2.save-update :  执行保存和更改操作时进行级联操作
3.delete :  执行删除操作时进行级联操作
4.none : 对所有操作不进行级联操作       默认

cascade属性的设置往往会带来性能上的变动,请谨慎设置。
例如:对district对象进行保存或更改操作时,district对象不一定有关联的street对象,或street对象不一定也需要更新,但是删除district对象时同时删除它所关联的street对象
因此:将cascade属性设置为all是不恰当的,应该设置为delete

Hibernate: insert into district (name, id) values (?, ?)
Hibernate: insert into street (name, district_id, id) values (?, ?, ?)
Hibernate: update street set district_id=? where id=?
1.第一条语句:比较好理解,插入新的区数据
2.第二天语句:这里为什么出现insert街道呢?我们并没有编写session.save(street)?
答案:其实我们在district端设置了级联更新(cascade=”all”)
也即是说,当HIbernate在向district插入”新“对象记录时,会检查“district”对象所关联的属性(就是<set>对应的属性)是否发生变化,如果发生变化就按设定的内容进行操作。因为调用了district.getStreet().add(street),所有Hibenate插入district时候,也一同把它所关联的瞬时状态的对象一同插入到对应的表中区。

Hibernate: update street set district_id=? where id=?
3.第三条语句:是update语句,为什么重复更新记录?
答:Hibernate将district与street之间的关联交由district来维持,就district而言,它要先储存自己,然后储存它所包括的多个street,之后对每一个street更新(update)对自己(district)的关联。
就district而言,它并不知道它所包括的street是不是已存储的对象,或者即使是已存储对象,也不知道street表格上的district_id是不是参考至district表格的id
所以,它必须针对自己所有包括的street对象进行更新,以确保street表格上的district_id是指向自己的。

正因为如此,所以Hibernate“怕”在进行”district.getStreet().add(street)”这样操作时,出现意外情况(如street.getClss=null,street没有所属的区)
存在外键不一致的情况。所有出现了这条多余的update语句。
也就是由one-to-many中一的一方(district端)主动维护外键,以保证所有包含district对象的集合里的所有street对象都要与自己(district)有外键关联。
通俗讲:每年开学新生报到,班级老师主动邀请同学,而不是同学自己来报到。可想而知效率怎么样?
Hiberate有没有提供解决这种情况的办法呢?
当然有:那就是设置inverse属性!!

posted @ 2017-05-28 11:14  日出东海落西山  阅读(4688)  评论(0编辑  收藏  举报