原文鏈接:http://lijiejava.iteye.com/blog/776587
舉例如下
Customer類:
- public class Customer {
- private int id;
- private String name;
- private Set orders = new HashSet();
- •••
- }
即Customer類具有一個set集合屬性orders,其中Order是一個普通的類:
- public class Order {
- private int id;
- private String orderName;
- •••
- }
數據庫中表的結構:
- t_customer: 兩個字段:id name
- t_order: 三個字段:id orderName customerid
Customer類的映射文件:Customer.hbm.xml (Order類的映射文件忽略)
- <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>
執行如下代碼:
- 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語句如下:
- 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=?
查看數據庫:
- 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集合中的對象,那麼在更新時將會拋出如下異常:
- 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",即:
- •••
- <set name="orders" cascade="save-update" inverse="true" lazy="false">
- <key column="customerid"/>
- <one-to-many class="test.Order"/>
- </set>
- •••
同樣執行上述代碼,發出如下語句:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName) values (?)
- Hibernate: insert into t_order (orderName) values (?)
相比上一次執行,少了兩條update語句,查看數據庫:
- 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類代碼:
- public class Order {
- private int id;
- private String orderName;
- private Customer customer;
- •••
- }
Order.hbm.xml:
- <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語句:
- 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字段,查看數據庫表:
- 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);
修改上述代碼爲:
- •••
- 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);
- •••
執行上述代碼,發出如下語句:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
查看數據庫:
- t_customer : t_order:
- id | name id | orderName | customerid
- 1 aaa 1 o1 1
- 2 o2 1
發現已經設置了customerid的值。
在一對多關聯中,在多的一方設置inverse="true",有助於性能的改善。通過上述分析可以發現少了update語句。