您的位置:首页 > 产品设计 > UI/UE

Hibernate中inverse="true"的理解

2015-10-26 16:57 435 查看



Hibernate中inverse="true"的理解

博客分类: 

Hibernate
HibernateJavaCC++C# 

举例如下 

Customer类: 

Java代码  


public class Customer {   

    private int id;   

    private String name;  

private Set orders = new HashSet();  

•••  

}  

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

Java代码  


public class Order {   

    private int id;   

    private String orderName;  

•••  

}  

数据库中表的结构: 

Java代码  


t_customer:  两个字段:id  name  

t_order:     三个字段:id  orderName  customerid  

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

Java代码  


<hibernate-mapping>  

    <class name="test.Customer" table="t_customer" lazy="false">    

        <id name="id">   

           <generator class="native"/>  

        </id>    

        <property name="name"/>    

        <set name="orders"  cascade="save-update"  lazy="false">  

           <key column="customerid"/>  

           <one-to-many class="test.Order"/>  

        </set>  

    </class>   

</hibernate-mapping>  

执行如下代码: 

Java代码  


Set orders = new HashSet();   

              

Order o1 = new Order();  

o1.setOrderName("o1");   

Order o2 = new Order();  

o2.setOrderName("o2");     

orders.add(o1);  

orders.add(o2);       

              

Customer c = new Customer();  

c.setName("aaa");  

c.setOrders(orders);    

  

session.save(c);   

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

Java代码  


Hibernate: insert into t_customer (name) values (?)  

Hibernate: insert into t_order (orderName) values (?)  

Hibernate: insert into t_order (orderName) values (?)  

Hibernate: update t_order set customerid=? where id=?  

Hibernate: update t_order set customerid=? where id=?  

查看数据库: 

Java代码  


t_customer :                    t_order:     

  

id   |  name                   id   |   orderName   |   customerid   

1       aaa                    1           o1              1  

                               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代码  


Hibernate: insert into t_customer (name) values (?)  

Hibernate: update t_order set customerid=? where id=?  

org.hibernate.TransientObjectException: test.Order  

••••••  

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

现在设置cascade="save-update",同时设置inverse="true",即: 

Java代码  


•••  

<set name="orders" cascade="save-update" inverse="true" lazy="false">  

    <key column="customerid"/>  

    <one-to-many class="test.Order"/>  

</set>    

•••  

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

Java代码  


Hibernate: insert into t_customer (name) values (?)  

Hibernate: insert into t_order (orderName) values (?)  

Hibernate: insert into t_order (orderName) values (?)  

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

Java代码  


t_customer :                    t_order:     

  

id   |  name                   id   |   orderName   |   customerid   

1       aaa                    1           o1              NULL  

                               2           o2              NULL  

发现t_order表中customerid的值为NULL,这是由于设置了inverse="true",它意味着 

Customer不再作为主控方,而将关联关系的维护工作交给关联对象Orders来完成。在保存Customer时,Customer不在关心Orders的customerid属性,必须由Order自己去维护,即设置order.setCustomer(customer); 

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

修改Order类代码: 

Java代码  


public class Order {   

    private int id;   

    private String orderName;    

    private Customer customer;  

•••  

}  

Order.hbm.xml: 

Java代码  


<hibernate-mapping>  

    <class name="test.Order" table="t_order">    

        <id name="id">   

           <generator class="native"/>  

        </id>    

        <property name="orderName"/>     

        <many-to-one name="customer" column="customerid"/>   

    </class>   

</hibernate-mapping>  

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

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

Java代码  


Hibernate: insert into t_customer (name) values (?)  

Hibernate: insert into t_order (orderName, customerid) values (?, ?)  

Hibernate: insert into t_order (orderName, customerid) values (?, ?)   

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

Java代码  


t_customer :                    t_order:     

  

id   |  name                   id   |   orderName   |   customerid   

1       aaa                    1           o1              NULL  

                               2           o2              NULL  

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

order.setCustomer(customer); 

修改上述代码为: 

Java代码  


•••  

Customer c = new Customer();  

              

Set orders = new HashSet();   

Order o1 = new Order();  

o1.setOrderName("o1");   

o1.setCustomer(c);  

Order o2 = new Order();  

o2.setOrderName("o2");  

o2.setCustomer(c);  

orders.add(o1);  

orders.add(o2);       

              

c.setName("aaa");  

c.setOrders(orders);   

              

session.save(c);   

•••   

   

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

Java代码  


Hibernate: insert into t_customer (name) values (?)  

Hibernate: insert into t_order (orderName, customerid) values (?, ?)  

Hibernate: insert into t_order (orderName, customerid) values (?, ?)  

查看数据库: 

Java代码  


t_customer :                    t_order:     

  

id   |  name                   id   |   orderName   |   customerid   

1       aaa                    1           o1              1  

                               2           o2              1  

发现已经设置了customerid的值。 

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

分享到: 

 


Spring的LocalSessionFactoryBean | Struts2集成Spring的讨论

2010-10-02 08:57

浏览 16155

评论(7)

分类:企业架构

相关推荐


评论


7 楼 u010214546 2015-05-22  

握着橄榄枝的人 写道

在一对多关联中,在多的一方设置inverse="true",有助于性能的改善。通过上述分析可以发现少了update语句。 这句话说错了吧,是在一对多的关联中,在1的一方设置inverse="true",让多的一方来维护关系,我看你也是这么做的啊,你不是在1的一方设置这个inverse="true",然后少了更新语句吗。

我也同意你的说法,我觉得是博主笔误了。

6 楼 握着橄榄枝的人 2014-01-16  
在一对多关联中,在多的一方设置inverse="true",有助于性能的改善。通过上述分析可以发现少了update语句。 这句话说错了吧,是在一对多的关联中,在1的一方设置inverse="true",让多的一方来维护关系,我看你也是这么做的啊,你不是在1的一方设置这个inverse="true",然后少了更新语句吗。

5 楼 幕风落雨 2013-08-13  
很全面详细


4 楼 yangyingcan2012 2013-06-19  


 讲得比较好,学习了

3 楼 feipigzi 2012-07-19  

w156445045 写道

目前SSH项目中都是这么做的,问下是不是实际的项目中都是这种多对多的关联关系呢?

我用myeclipse的逆向生成的代码也是这种多对多的,

<set name="enterprisePowers" inverse="true" cascade="all">

            <key>

                <column name="eno" precision="18" scale="0" not-null="true" />

            </key>

            <one-to-many class="com.yaxing.pojo.EnterprisePower" />

        </set>

cascade 这个是自己加的~

以上说的是一对多的关系

2 楼 w156445045 2011-12-30  
上面写错了,是双向关系,是不是都建立的这种双向的关系呢? 

不是说多对一才是最适合关系数据库的外键的吗?

1 楼 w156445045 2011-12-30  
目前SSH项目中都是这么做的,问下是不是实际的项目中都是这种多对多的关联关系呢? 

我用myeclipse的逆向生成的代码也是这种多对多的, 

<set name="enterprisePowers" inverse="true" cascade="all"> 

            <key> 

                <column name="eno" precision="18" scale="0" not-null="true" /> 

            </key> 

            <one-to-many class="com.yaxing.pojo.EnterprisePower" /> 

        </set> 

cascade 这个是自己加的~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: