Hibernate一对多关联映射及cascade级联操作
我們以客戶(Customer)與訂單(Order)為例
實體類創建
Order訂單實體類
//訂單-----多的一方 public class Order {private Integer id;private Double money;private String receiverInfo; // 收貨地址// 訂單與客戶關聯private Customer c; // 描述訂單屬于某一個客戶public Customer getC() {return c;}public void setC(Customer c) {this.c = c;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}public String getReceiverInfo() {return receiverInfo;}public void setReceiverInfo(String receiverInfo) {this.receiverInfo = receiverInfo;}}Customer客戶實體類
//客戶 ------一的一方 public class Customer {private Integer id; // 主鍵private String name; // 姓名// 描述客戶可以有多個訂單private Set<Order> orders = new HashSet<Order>();public Set<Order> getOrders() {return orders;}public void setOrders(Set<Order> orders) {this.orders = orders;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}Hbm映射文件編寫
Order.hbm.xml配置文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="cn.nwtxxb.oneToMany.Order" table="t_order"><id name="id" column="c_id"><generator class="identity" /></id><property name="money" column="c_money" /><property name="receiverInfo" column="c_receiverInfo" length="50"/><!-- 多對一 --><many-to-one fetch="join" lazy="false" name="c" class="cn.nwtxxb.oneToMany.Customer" column="c_customer_id"></many-to-one><!-- name屬性它描述的是Order類中的一的一方的屬性名稱 Customer c;class 代表一的一方的類型column 描述的是一對多,在多的一方產生的外鍵的名稱 c_customer_id--></class></hibernate-mapping>Customer.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping><class name="cn.nwtxxb.oneToMany.Customer" table="t_customer"><id name="id" column="c_id"><generator class="identity" /></id><property name="name" column="c_name" length="20" /><!-- 一個客戶關聯多個訂單 --><set name="orders" inverse="true" cascade="save-update"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" /></set><!-- 使用set來描述在一的一方中關聯的多 Set<Order>,它的name屬性就是set集合的名稱 key:它主要描述關聯的多的一方產生的外鍵名稱,注意要與多的一方定義的外鍵名稱相同 one-to-many 描述集合中的類型 --></class> </hibernate-mapping>測試保存
public class OneToManyTest {// 測試保存@Testpublic void test1() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立關系// 2.3.1 訂單關聯客戶o1.setC(c);o2.setC(c);// 2.3.2 客戶關聯訂單c.getOrders().add(o1);c.getOrders().add(o2);session.save(o1);session.save(o2);session.save(c);// 3.事務提交,關閉session.getTransaction().commit();session.close();} }上面操作是一種雙向關聯
問題:我們可不可以只保存訂單或只保存客戶完成保存操作?
測試單向關聯保存
// 測試保存---單向操作(保存訂單并自動保存客戶)@Testpublic void test2() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立關系// 2.3.1 訂單關聯客戶o1.setC(c);o2.setC(c);session.save(o1); // o1是一個持久化對象session.save(o2); // o2是一個持久化對象// 3.事務提交,關閉session.getTransaction().commit();session.close();}org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cn.nwtxxb.oneToMany.Customer
…………..
這個異常代表提一個持久化對象關聯了一個瞬時對象。
我們可以使用級聯操作來解決上述的問題.
我們現在要做的是保存訂單時保存客戶,需要在訂單的hbm配置文件中修改
設置cascade=save-update 那么在保存訂單時就可以自動將客戶保存。
如果我們要完成保存客戶時,保存訂單
雙向關聯保存
我們在開發中要配置雙向關聯配置。———可以通過任意一方來操作對方
在操作代碼,盡量來要進行單向關聯。——可以盡量資源浪費。
在雙向關聯中,會存在多余的update語句。
我們可以使用inverse屬性來設置,雙向關聯時由哪一方來維護表與表之間的關系。
Inverse它的值如果為true代表,由對方來維護外鍵。
Inverse它的值如果為false代表,由本方來維護外鍵。
關于inverse的取值:
外鍵在哪一個表中,我們就讓哪一方來維護外鍵。
對象導航
級聯刪除
我們在刪除客戶時,也要刪除訂單,如果沒有做級聯,那么這個操作是不允許。
為了維護數據完整性
delete-orphan用法
<!-- 一個客戶關聯多個訂單 --> <set name="orders" inverse="true" cascade="delete-orphan"><key column="c_customer_id" /><one-to-many class="cn.nwtxxb.oneToMany.Order" /> </set>測試類
public class OneToManyTest {// 級聯 cascade= delete-orphan@Testpublic void test6() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 得到客戶Customer c = session.get(Customer.class, 2);// 得到客戶的訂單Order o = session.get(Order.class, 6);c.getOrders().remove(o);// 3.事務提交,關閉session.getTransaction().commit();session.close();}// 測試級聯刪除@Testpublic void test5() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 操作----刪除訂單時,不需要刪除客戶,當我們刪除一個客戶時,應該將客戶對應訂單也刪除。Customer c = session.get(Customer.class, 1);session.delete(c);// 刪除客戶?訂單是否會刪除?// 3.事務提交,關閉session.getTransaction().commit();session.close();}// 測試一對多對象導航@Testpublic void test4() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");Order o3 = new Order();o3.setMoney(3000d);o3.setReceiverInfo("深圳");// 描述關系// o1要關聯co1.setC(c);// c要關聯o2 o3c.getOrders().add(o2);c.getOrders().add(o3);session.save(o1);// 3.事務提交,關閉session.getTransaction().commit();session.close();}// 測試保存---單向操作(保存客戶并自動保存訂單)@Testpublic void test3() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立關系// 2.3.1 客戶與訂單關聯c.getOrders().add(o1);c.getOrders().add(o2);session.save(c);// 保存客戶// 3.事務提交,關閉session.getTransaction().commit();session.close();}// 測試保存---單向操作(保存訂單并自動保存客戶)@Testpublic void test2() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立關系// 2.3.1 訂單關聯客戶o1.setC(c);o2.setC(c);session.save(o1); // o1是一個持久化對象session.save(o2); // o2是一個持久化對象// 3.事務提交,關閉session.getTransaction().commit();session.close();}// 測試保存@Testpublic void test1() {// 1.得到sessionSession session = HibernateUtils.openSession();session.beginTransaction();// 2.操作// 2.1創建一個客戶Customer c = new Customer();c.setName("張三");// 2.2創建兩個訂單Order o1 = new Order();o1.setMoney(1000d);o1.setReceiverInfo("北京");Order o2 = new Order();o2.setMoney(2000d);o2.setReceiverInfo("上海");// 2.3建立關系// 2.3.1 訂單關聯客戶o1.setC(c);o2.setC(c);// 2.3.2 客戶關聯訂單c.getOrders().add(o1);c.getOrders().add(o2);session.save(o1);session.save(o2);session.save(c);// 3.事務提交,關閉session.getTransaction().commit();session.close();} }HibernateUtils工具類
public class HibernateUtils {private static Configuration config;private static SessionFactory sessionFactory;static{config=new Configuration().configure();sessionFactory=config.buildSessionFactory();}public static Session openSession(){return sessionFactory.openSession();} }cascade級聯操作總結
使用cascade可以完成級聯操作
它可常用取值:
none這是一個默認值
save-update,當我們配置它時,底層使用save update或save-update完成操作,級聯保存臨時對象,如果是游離對象,會執行update.
delete 級聯刪除
delete-ophan 刪除與當前對象解除關系的對象。
all 它包含了save-update delete操作
all-delete-orphan 它包信了delete-orphan與all操作
問題:cascade與inverse有什么區別?
cascade它是完成級聯操作
Inverse它只有在雙向關聯情況下有作用,它來指定由哪一方維護外鍵。
總結
以上是生活随笔為你收集整理的Hibernate一对多关联映射及cascade级联操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibernate关联映射-数据对象三种
- 下一篇: Hibernate注解开发-PO类注解配