对Hibernate中关系维护方和级联的理解
2017-08-08 09:56
267 查看
级联:在双向多对一中,有一方设置了级联,如@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)(它是在多的一方设置了级联),它的作用就是在操作设置级联的那一方时会影响另一方(比如在保存时,当然前提是要对对方属性有设置,不然就是空,那么对方也会插入数据,但对方插入数据时,有没有本方的属性就要看本方是不是关系维护方了)。(如果某一方没有设置级联,那么它在操作时不会影响另一方)
关系维护方:在双向多对一中,一般会设置多的一方为关系维护方。比如@OneToMany(fetch = FetchType.LAZY, mappedBy = "tblUser")(注解方式不允许一的一方设为关系维护方)。关系维护方是指在该方做增删改时,会去维护另一方。以Order和User为例,当有order.setUser(user),且user没有setOrders()时,其中Order为关系维护方,那么当session.save(order)时,会去维护User对象,但此时如果Order没有开启级联操作,那么就会报错org.hibernate.TransientObjectException:
object references an unsaved transient instance - save the transient instance before flushing。也就是说:有级联的情况下操作关系维护方才能成功。当然,如果order没有setUser,那么不需要级联也是可以的。当多的一方满足1、关系维护方和2、设置了级联属性。那么在做save操作前,只需要对多的一方做设置(如order.setUser(user))就可以了,不需要一的一方做设置(即不需要user.setOrders())。所以如果是一的一方做save操作时,必须两方都做设置(order.setUser(user)和user.setOrders())。因为在注解中,一的一方不能满足它是关系维护方这个条件。非关系维护方在有无级联的情况下都能操作本方对象。
所以我们将一的一方是设置级联,多的一方不设置级联,但设置为关系维护方是不合理的,我们可以将多的一方也设置级联,但如果将多的一方的cascade 设为 CascadeType.ALL,那么如果删除多的一方,会将一的一方也删除,所以设为 cascade = {CascadeType.PERSIST,CascadeType.REFRESH}即可。
注意一个问题:
多的一方默认使用饥饿加载,一的一方默认使用懒加载。当多的一方使用delete时,没有级联操作时,即使是维护方(维护方一定要指定)也能做删除操作。但是如果此时一的一方使用饥饿加载,那么多的一方使用delete时会报错:org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)。
那怎么办?解除要删除对象的多对一关系,两方都要设置,因为此时一的一方已经加载了多的一方,做法比如(order.getTblUser().getTblOrders().remove(order);
order.setTblUser(null);)。本来我以为维护方只要设置order.setTblUser(null)即可。但因为session缓存中一的一方已经有了它所对应的所有多的一方,此时它不能被删。
关系维护方:在双向多对一中,一般会设置多的一方为关系维护方。比如@OneToMany(fetch = FetchType.LAZY, mappedBy = "tblUser")(注解方式不允许一的一方设为关系维护方)。关系维护方是指在该方做增删改时,会去维护另一方。以Order和User为例,当有order.setUser(user),且user没有setOrders()时,其中Order为关系维护方,那么当session.save(order)时,会去维护User对象,但此时如果Order没有开启级联操作,那么就会报错org.hibernate.TransientObjectException:
object references an unsaved transient instance - save the transient instance before flushing。也就是说:有级联的情况下操作关系维护方才能成功。当然,如果order没有setUser,那么不需要级联也是可以的。当多的一方满足1、关系维护方和2、设置了级联属性。那么在做save操作前,只需要对多的一方做设置(如order.setUser(user))就可以了,不需要一的一方做设置(即不需要user.setOrders())。所以如果是一的一方做save操作时,必须两方都做设置(order.setUser(user)和user.setOrders())。因为在注解中,一的一方不能满足它是关系维护方这个条件。非关系维护方在有无级联的情况下都能操作本方对象。
所以我们将一的一方是设置级联,多的一方不设置级联,但设置为关系维护方是不合理的,我们可以将多的一方也设置级联,但如果将多的一方的cascade 设为 CascadeType.ALL,那么如果删除多的一方,会将一的一方也删除,所以设为 cascade = {CascadeType.PERSIST,CascadeType.REFRESH}即可。
注意一个问题:
多的一方默认使用饥饿加载,一的一方默认使用懒加载。当多的一方使用delete时,没有级联操作时,即使是维护方(维护方一定要指定)也能做删除操作。但是如果此时一的一方使用饥饿加载,那么多的一方使用delete时会报错:org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)。
那怎么办?解除要删除对象的多对一关系,两方都要设置,因为此时一的一方已经加载了多的一方,做法比如(order.getTblUser().getTblOrders().remove(order);
order.setTblUser(null);)。本来我以为维护方只要设置order.setTblUser(null)即可。但因为session缓存中一的一方已经有了它所对应的所有多的一方,此时它不能被删。
相关文章推荐
- hibernate之xml映射文件关系维护,懒加载,级联
- 从hibernate源代码角度解析, 关系维护 ,dirty检查 ,脏数据检查.. 级联区别 cascade区别.
- Hibernate中使用的集合类型,级联和关系维护
- hibernate之xml映射文件关系维护,懒加载,级联
- Hibernate<五> 级联和关系维护
- 13 级联和关系维护(Cascade 和Inverse)
- [置顶] 关于jpa、hibernate的级联关系及注解OneToOne等注解解释
- 初识Hibernate(三)之多表关系维护
- hibernate级联关系 -----一对一
- 详细理解java Hibernate 或 JPA的级联操作
- hibernate级联关系思考
- 处理hibernate多重级联关系下的删除解决方法
- 关于hibernate的关系映射的问题一些理解和笔记
- (7) hibernate之级联cascade和关系维持inverse
- 初识Hibernate(三)之多表关系维护
- Hibernate(3)关系映射之一对多级联
- hibernate 具有主外键关系的多表级联保存
- SSH与SSM学习之hibernate19——多对一一对多关系维护
- Hibernate 学习笔记 之 一对多关系 及其 级联操作
- 深入Hibernate表关系维护