`

Hibernate中inverse="true"的理解

阅读更多

转自:http://lijiejava.iteye.com/blog/776587

举例如下 

Customer类: 

Java代码  收藏代码
  1. public class Customer {   
  2.     private int id;   
  3.     private String name;  
  4. private Set orders = new HashSet();  
  5. •••  
  6. }  


即Customer类具有一个set集合属性orders,其中Order是一个普通的类: 

Java代码  收藏代码
  1. public class Order {   
  2.     private int id;   
  3.     private String orderName;  
  4. •••  
  5. }  


数据库中表的结构: 

Java代码  收藏代码
  1. t_customer:  两个字段:id  name  
  2. t_order:     三个字段:id  orderName  customerid  



Customer类的映射文件:Customer.hbm.xml  (Order类的映射文件忽略) 

Java代码  收藏代码
  1. <hibernate-mapping>  
  2.     <class name="test.Customer" table="t_customer" lazy="false">    
  3.         <id name="id">   
  4.            <generator class="native"/>  
  5.         </id>    
  6.         <property name="name"/>    
  7.         <set name="orders"  cascade="save-update"  lazy="false">  
  8.            <key column="customerid"/>  
  9.            <one-to-many class="test.Order"/>  
  10.         </set>  
  11.     </class>   
  12. </hibernate-mapping>  


执行如下代码: 

Java代码  收藏代码
  1. Set orders = new HashSet();   
  2.               
  3. Order o1 = new Order();  
  4. o1.setOrderName("o1");   
  5. Order o2 = new Order();  
  6. o2.setOrderName("o2");     
  7. orders.add(o1);  
  8. orders.add(o2);       
  9.               
  10. Customer c = new Customer();  
  11. c.setName("aaa");  
  12. c.setOrders(orders);    
  13.   
  14. session.save(c);   


此时Hibernate发出的sql语句如下: 

Java代码  收藏代码
  1. Hibernate: insert into t_customer (name) values (?)  
  2. Hibernate: insert into t_order (orderName) values (?)  
  3. Hibernate: insert into t_order (orderName) values (?)  
  4. Hibernate: update t_order set customerid=? where id=?  
  5. Hibernate: update t_order set customerid=? where id=?  


查看数据库: 

Java代码  收藏代码
  1. t_customer :                    t_order:     
  2.   
  3. id   |  name                   id   |   orderName   |   customerid   
  4. 1       aaa                    1           o1              1  
  5.                                2           o2              1   


保存Customer对象时,首先发出insert into t_customer (name) values (?)语句将c同步到数据库,由于在<set>映射中设置cascade="save-update",所以会同时保存orders集合中的Order类型的o1,o2对象(如果没有这个设置,即cascade="save-update"),那么Hibenrate不会自动保存orders集合中的对象,那么在更新时将会抛出如下异常: 

Java代码  收藏代码
  1. Hibernate: insert into t_customer (name) values (?)  
  2. Hibernate: update t_order set customerid=? where id=?  
  3. org.hibernate.TransientObjectException: test.Order  
  4. ••••••  


抛出这一异常的原因是:<set>映射默认"inverse=fasle"即由Customer对象作为主控方,那么它要负责关联的维护工作,在这里也就是负责更新t_order表中的customerid字段的值,但由于未设置cascade="save-update",所以orders集合中的对象不会在保存customer时自动保存,因此会抛出异常(如果未设置,需要手动保存)。 
现在设置cascade="save-update",同时设置inverse="true",即: 

Java代码  收藏代码
  1. •••  
  2. <set name="orders" cascade="save-update" inverse="true" lazy="false">  
  3.     <key column="customerid"/>  
  4.     <one-to-many class="test.Order"/>  
  5. </set>    
  6. •••  


同样执行上述代码,发出如下语句: 

Java代码  收藏代码
  1. Hibernate: insert into t_customer (name) values (?)  
  2. Hibernate: insert into t_order (orderName) values (?)  
  3. Hibernate: insert into t_order (orderName) values (?)  


相比上一次执行,少了两条update语句,查看数据库: 

Java代码  收藏代码
  1. t_customer :                    t_order:     
  2.   
  3. id   |  name                   id   |   orderName   |   customerid   
  4. 1       aaa                    1           o1              NULL  
  5.                                2           o2              NULL  


发现t_order表中customerid的值为NULL,这是由于设置了inverse="true",它意味着 
Customer不再作为主控方,而将关联关系的维护工作交给关联对象Orders来完成。在保存Customer时,Customer不在关心Orders的customerid属性,必须由Order自己去维护,即设置order.setCustomer(customer); 

如果需要通过Order来维护关联关系,那么这个关联关系转换成双向关联。 
修改Order类代码: 

Java代码  收藏代码
  1. public class Order {   
  2.     private int id;   
  3.     private String orderName;    
  4.     private Customer customer;  
  5. •••  
  6. }  


Order.hbm.xml: 

Java代码  收藏代码
  1. <hibernate-mapping>  
  2.     <class name="test.Order" table="t_order">    
  3.         <id name="id">   
  4.            <generator class="native"/>  
  5.         </id>    
  6.         <property name="orderName"/>     
  7.         <many-to-one name="customer" column="customerid"/>   
  8.     </class>   
  9. </hibernate-mapping>  


此时数据库中表的结构不会变化。 

再次执行上述代码,发出如下sql语句: 

Java代码  收藏代码
  1. Hibernate: insert into t_customer (name) values (?)  
  2. Hibernate: insert into t_order (orderName, customerid) values (?, ?)  
  3. Hibernate: insert into t_order (orderName, customerid) values (?, ?)   


发现在保存Order对象时为customerid字段赋值,因为Order对象中拥有Customer属性,对应customerid字段,查看数据库表: 

Java代码  收藏代码
  1. t_customer :                    t_order:     
  2.   
  3. id   |  name                   id   |   orderName   |   customerid   
  4. 1       aaa                    1           o1              NULL  
  5.                                2           o2              NULL  


发现customerid的值仍为NULL,因为在上述代码中并未设置Order对象的Customer属性值,由于设置了inverse="true",所以Order对象需要维护关联关系,所以必须进行设置,即 
order.setCustomer(customer); 

修改上述代码为: 

Java代码  收藏代码
  1. •••  
  2. Customer c = new Customer();  
  3.               
  4. Set orders = new HashSet();   
  5. Order o1 = new Order();  
  6. o1.setOrderName("o1");   
  7. o1.setCustomer(c);  
  8. Order o2 = new Order();  
  9. o2.setOrderName("o2");  
  10. o2.setCustomer(c);  
  11. orders.add(o1);  
  12. orders.add(o2);       
  13.               
  14. c.setName("aaa");  
  15. c.setOrders(orders);   
  16.               
  17. session.save(c);   
  18. •••   
  19.    


执行上述代码,发出如下语句: 

Java代码  收藏代码
  1. Hibernate: insert into t_customer (name) values (?)  
  2. Hibernate: insert into t_order (orderName, customerid) values (?, ?)  
  3. Hibernate: insert into t_order (orderName, customerid) values (?, ?)  


查看数据库: 

Java代码  收藏代码
  1. t_customer :                    t_order:     
  2.   
  3. id   |  name                   id   |   orderName   |   customerid   
  4. 1       aaa                    1           o1              1  
  5.                                2           o2              1  


发现已经设置了customerid的值。 

在一对多关联中,在多的一方设置inverse="true",有助于性能的改善。通过上述分析可以发现少了update语句。

分享到:
评论

相关推荐

    hibernate 3中的缓存小结

    &lt;set name="products" table="products" cascade="all" inverse="true"&gt; &lt;!-- Hibernate只会缓存对象的简单属性的值, 要缓存集合属性,必须在集合元素中也加入子元素 而Hibernate仅仅是把与当前持久对象关联的...

    hibernate学习5之one-to-many双向关联.docx

    如果在”一“一端维护一对多关联关系,hibernate会发出多余的udpate语句,所以我们一般在多的一端来维护关联关系。 加上inverse="true"这个属性,就可以强制在多的一端维护关系了。

    hibernate总结

    &lt;set name="emps" inverse ="true" lazy="true" cascade="none" batch-size="2" fetch="join" &gt; &lt;column name="deptid" /&gt; &lt;one-to-many class="org.wllt.www.po.Emp" /&gt; &lt;/hibernate-mapping&gt; ...

    Hibernate注释大全收藏

    Hibernate注释大全收藏 声明实体Bean @Entity public class Flight implements Serializable { Long id; @Id public Long getId() { return id; } public void setId(Long id) { this.id = id; } } @Entity ...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即检索(使用batch-size属性)  16.3.5 用带子查询的select语句整批量初始化orders...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即检索(使用batch-size属性)  16.3.5 用带子查询的select语句整批量初始化orders...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即检索(使用batch-size属性)  16.3.5 用带子查询的select语句整批量初始化orders...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     16.3.2 延迟检索(lazy属性为默认值“true”)  16.3.3 增强延迟检索(lazy属性为“extra”)  16.3.4 批量延迟检索和批量立即检索(使用batch-size属性)  16.3.5 用带子查询的select语句整批量初始化orders...

    jdbc基础和参考

    inverse="true":让其中一方放弃对关联关系的维护 一般在做双向多对一(一对多)关联关系映射的时候,一般会设置让一的一方放弃对关联关系的维护,以减少不必要的更新语句 一对一: 基于外键的一对一 Wife Husband...

    Java面试宝典2010版

    9、hibernate的inverse属性的作用? 13、在DAO中如何体现DAO设计模式? 14、spring+Hibernate中委托方案怎么配置? 15、spring+Hibernate中委托方案怎么配置? 16. hibernate进行多表查询每个表中各取几个字段,也...

    最新Java面试宝典pdf版

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各取几...

    Java面试笔试资料大全

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各取几...

    JAVA面试宝典2010

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各取几...

    Java面试宝典-经典

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各取几...

    java面试题大全(2012版)

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各取几...

    Java面试宝典2012版

    9、hibernate的inverse属性的作用? 122 13、在DAO中如何体现DAO设计模式? 123 14、spring+Hibernate中委托方案怎么配置? 123 15、spring+Hibernate中委托方案怎么配置? 123 16. hibernate进行多表查询每个表中各...

    java面试宝典2012

    9、hibernate的inverse属性的作用? 134 13、在DAO中如何体现DAO设计模式? 134 14、spring+Hibernate中委托方案怎么配置? 134 15、spring+Hibernate中委托方案怎么配置? 134 16. hibernate进行多表查询每个表中各取几...

Global site tag (gtag.js) - Google Analytics