Hibernate中inverse="true"的理解

Posted DarJeely

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate中inverse="true"的理解相关的知识,希望对你有一定的参考价值。

Hibernate中inverse="true"的理解

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

1. public class Order {   

2. private int id;   

3. private String orderName;  

4. •••

5. }  

数据库中表的结构:

Java代码 clip_image001[1]

1. t_customer:  两个字段:id  name  

2. t_order:     三个字段:id  orderName  customerid  

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

Java代码 clip_image001[2]

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代码 clip_image001[3]

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代码 clip_image001[4]

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代码 clip_image001[5]

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代码 clip_image001[6]

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代码 clip_image001[7]

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代码 clip_image001[8]

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代码 clip_image001[9]

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代码 clip_image001[10]

1. public class Order {   

2. private int id;   

3. private String orderName;    

4. private Customer customer;  

5. •••

6. }  

Order.hbm.xml:

Java代码 clip_image001[11]

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代码 clip_image001[12]

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代码 clip_image001[13]

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代码 clip_image001[14]

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代码 clip_image001[15]

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代码 clip_image001[16]

1. t_customer :                    t_order:     

2.

3. id   |  name                   id   |   orderName   |   customerid   

4. 1       aaa                    1           o1              1

5. 2           o2              1

发现已经设置了customerid的值。

以上是关于Hibernate中inverse="true"的理解的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate inverse=''true" 和获得一对多时的问题

hibernate中inverse的用法

hibernate中inverse属性详解

一口一口吃掉Hibernate——Hibernate中inverse的用法

hibernate中 inverse的用法(转载)

Hibernate中的inverse