hibernate:一对多关系中的inverse 和cascade

来源:互联网 发布:测绘工程就业前景知乎 编辑:程序博客网 时间:2024/04/26 05:41

 inverse 与 cascade 是正交的关系,不管 inverse 设置为什么值, 只要 cascade 设置为 “save-update”或者 “all”,当操作 Brand 或 Product 时,相关对象的操作(如果有)也会发生,但关系的建立则要看 inverse的值或者是对哪方进行操作。比如以下的代码,在不同的配置下产生不同的效果:(Brand 与 Product 是一对多的关系)

一、只操作 Brand:

   1. Brand b = new Brand();  
   2. b.setName("brand4");          
   3.  
   4. Product p = new Product();  
   5. p.setName("4p");  
   6. p.setBrand(b);  
   7.           
   8. b.addProduct(p); 
      session.save(b);


inverse="true",两者的关系由 Product 管理:

   1. <set name="products" inverse="true" cascade="save-update"> 
   2.     <key column="f_brand_id" />
   3.     <one-to-many class="model.Product"/>          
   4. set> 


输出语句是:
Hibernate: insert into brand_t (f_name) values (?)
Hibernate: insert into product_t (f_name) values (?)

这样的product 的 f_brand_id 为空,即它们之间的关系没有建立起来。

inverse="false",两者的关系由 Brand 管理:

   1. <set name="products" inverse="false" cascade="save-update"> 
   2.     <key column="f_brand_id" /> 
   3.     <one-to-many class="model.Product"/>          
   4. set> 


输出语句是:
Hibernate: insert into brand_t (f_name) values (?)
Hibernate: insert into product_t (f_name) values (?)
Hibernate: update product_t set f_brand_id=? where f_id=?

这样两者的关系就建立起来了。

二、看看操作 Product 的情况:

   1. Brand b = new Brand();  
   2. b.setName("brand4");          
   3.  
   4. Product p = new Product();  
   5. p.setName("4p");  
   6. p.setBrand(b);  
   7.           
   8. session.save(p);

   1. <many-to-one name="brand" 
   2.     class="model.Brand" 
   3.     cascade="none" 
   4.     column="f_brand_id" /> 


这时保存会出现org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: model.Brand 的异常,原因是 Brand 还不是一个持久化的东西,如果设置为:
cascade="save-update" 或 "all" ,则同时保存Brand 和 Product,且两者的关系也建立起来。

这时有点不同的是如果加上 b.getProducts().add(p); 这段代码,inverse="false" 的情况下会额外产生一条语句(why?):
Hibernate: update product_t set f_brand_id=? where f_id=?

实际运用当中很多时候都是由多的一方维持两者的关联,一的一方则掌管着多的“生杀大权”。比如:
xml 代码

   1. <set name="products" inverse="true" cascade="all"> 
   2.     <key column="f_brand_id" /> 
   3.     <one-to-many class="model.Product"/> 
   4. set> 


   1. <many-to-one name="brand" 
   2.     class="model.Brand" 
   3.     cascade="none" 
   4.     column="f_brand_id" /> 


大家使用的情况又是怎样的呢?

 

inverse只有在集合映射中才有,当inverse = true,字面意思好像是反转,由对方来维护关系,但实际还要看对方的配置,实际意思就是我不维护这个关系。当inverse = false意思就是我要维护这个关系,维护关系表现在行动上就是对于加入到这个集合或者从集合中移除的对象,对它的外键进行更新操作,使它与自己关联起来,将它的外键值设为null就是与自己脱离关系,或者是对中间表的操作(增删中间表的关联记录)。

inverse不会去删除对方这个对象,而cascade则可以级联删除或插入对方。inverse作用的基础是对方这个对象在数据库中存在,与cascade配合使用,作用的顺序也是cascade在前inverse在后。

所以对于多对一双向关联,因为多方已经可以建立关联关系,所以在一方的多方集合中就没必要再维护关系了,一般会设inverse = true。
对于多对多双向关联来说,则至少要有一方设置进行关联维护。