对Hibernate中关系维护方和级联的理解

来源:互联网 发布:中国的软件怎么样 编辑:程序博客网 时间:2024/06/07 03:43

级联:在双向多对一中,有一方设置了级联,如@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缓存中一的一方已经有了它所对应的所有多的一方,此时它不能被删。


阅读全文
0 0
原创粉丝点击