论坛首页 Java企业应用论坛

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

浏览 13833 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-17   最后修改:2010-11-19
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" /> 


大家使用的情况又是怎样的呢?
   发表时间:2007-06-17  
。。。。。。
这个编辑器真的有问题,还是。。。
怎么后面的都没有啦,中间也断了。。。 
(谢谢版主帮我调出来
0 请登录后投票
   发表时间:2007-06-18  
这有什么奇怪的,b.addProduct(p);和b.getProducts().add(p);不是一样的嘛。你自己也说了inverse="false" 就是来管关系这个事情的嘛。
0 请登录后投票
   发表时间:2007-06-18  
问题是如果不加上b.addProduct(p);
在保存Product的同时也保存了Brand,且两者的关系也建立起来了。那干嘛还有加上b.addProduct(p); 让它操作多一次update呢。
0 请登录后投票
   发表时间:2007-06-19  
对于楼主说的inverse 与 cascade 是正交的关系不太理解是什么意思。

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

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

所以对于多对一双向关联,因为多方已经可以建立关联关系,所以在一方的多方集合中就没必要再维护关系了,一般会设inverse = true。
对于多对多双向关联来说,则至少要有一方设置进行关联维护。
1 请登录后投票
   发表时间:2007-06-19  
楼上表达的就是我理解的。
0 请登录后投票
   发表时间:2007-07-22  
引用
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 为空,即它们之间的关系没有建立起来。


为什么我这种情况是product的id不为空,而是正确的生成了,也就是说当inverse="false"时,对one一方作save操作时,它们之间的关系也被建立了?这是什么原因啊?
0 请登录后投票
   发表时间:2007-09-18  
inverse主要影响insert, update语句。。。
设置inverse的目的主要是在于由哪一方管理关联关系,说白了就是由哪一方来管理表的外键。。。
上面的Brand和Product是一对多的关系。。。
考虑下面的代码,

brand.getProducts().add(product);
product.setBrand(brand);

如果在set上不使用inverse="true",上面的两行代码会更新外键,显然没有必要。
如果使用了inverse="true",第一行不会更新外键操作,外键由第二行代码进行维护。

inverse不影响cascade操作
0 请登录后投票
   发表时间:2008-06-10  
是不是数学专业的?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics