zoukankan      html  css  js  c++  java
  • 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语句。

  • 相关阅读:
    详细解说python垃圾回收机制
    Vue-- 监听路由参数变化,数据无法更新 解决方案
    解决“只能通过Chrome网上应用商店安装该程序”的方法 ---离线安装谷歌浏览器插件
    axios POST提交数据的三种请求方式写法
    axios POST提交数据的三种请求方式写法
    vue+element后台系统 自己动手撸(一)
    element-ui中 table表格hover 修改背景色
    解决vue的{__ob__: observer}取值问题
    Vue [__ob__: Observer]取不到值问题的解决
    VUE监听路由变化的几种方式
  • 原文地址:https://www.cnblogs.com/1995hxt/p/5115020.html
Copyright © 2011-2022 走看看