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語句。

發佈了2 篇原創文章 · 獲贊 15 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章