JAVAWEB開發之Hibernate詳解(二)——Hibernate的持久化類狀態與轉換、以及一級快取詳解、關聯關係的對映(一對多、多對多、級聯)
阿新 • • 發佈:2019-01-08
Coursepackage cn.test.hibernate3.demo2; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import cn.test.hibernate3.demo2.Customer; import cn.test.hibernate3.demo2.Order; import cn.test.hibernate3.utils.HibernateUtils; /** * 一對多測試 為防止干擾,每次測試之前drop掉資料庫所有表 在測試刪除操作時,drop全部表後,再執行demo1 重新在資料庫生成資料 */ public class HibernateTest2 { @Test // 雙方都不配置級聯的情況下 // 向客戶表中插入一個客戶,在訂單表中插入兩個訂單 public void demo1() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定義一個客戶 Customer customer = new Customer(); customer.setCname("郭浩"); // 定義兩個訂單 Order order1 = new Order(); order1.setAddr("西三旗中騰"); Order order2 = new Order(); order2.setAddr("西三旗金燕龍"); // 建立關係 order1.setCustomer(customer); order2.setCustomer(customer); customer.getOrders().add(order1); customer.getOrders().add(order2); session.save(customer); session.save(order1); session.save(order2); tx.commit(); session.close(); } @Test // 儲存客戶和訂單的時候,是否可以只儲存其中一方? // 會報異常:一個持久態的物件關聯了一個瞬時態的物件 // org.hibernate.TransientObjectException: object references an unsaved // transient instance - save the transient instance before flushing: // cn.test.hibernate3.demo2.Order public void demo2() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定義客戶 Customer customer = new Customer(); customer.setCname("李小龍"); // 定義訂單 Order order = new Order(); order.setAddr("五道口"); order.setCustomer(customer); customer.getOrders().add(order); // 儲存的時候只儲存一方 session.save(customer); tx.commit(); session.close(); } @Test // 儲存客戶級聯儲存訂單—— 一方設定級聯多方 // <set>集合時客戶的關聯訂單物件的集合.所以在Customer.hbm.xml中<set>上配置一個屬性:cascade="save-update" public void demo3() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定義客戶: Customer customer = new Customer(); customer.setCname("郭浩"); // 定義訂單: Order order = new Order(); order.setAddr("西三旗中騰建華"); order.setCustomer(customer); customer.getOrders().add(order); // 儲存的時候只儲存一方: session.save(customer); tx.commit(); session.close(); } @Test // 儲存訂單級聯儲存客戶——在多方設定級聯儲存一方 // 在Order.hbm.xml中<many-to-one>配置cascade屬性:級聯儲存 public void demo4() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定義客戶: Customer customer = new Customer(); customer.setCname("郭浩"); // 定義訂單: Order order = new Order(); order.setAddr("西三旗中騰建華"); order.setCustomer(customer); customer.getOrders().add(order); // 儲存的時候只儲存一方: session.save(order); tx.commit(); session.close(); } @Test // 測試物件的導航關係——目前是雙向級聯儲存或更新關係 public void demo5() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定義一個客戶 Customer customer = new Customer(); customer.setCname("武藤蘭"); // 定義三個訂單 Order order1 = new Order(); order1.setAddr("西三旗"); Order order2 = new Order(); order2.setAddr("上地"); Order order3 = new Order(); order3.setAddr("五道口"); order1.setCustomer(customer); customer.getOrders().add(order2); customer.getOrders().add(order3); // session.save(order1); // 共傳送4條insert語句 // session.save(customer);// 共傳送3條insert語句 session.save(order2); // 共傳送1條insert語句 tx.commit(); session.close(); } @Test // 刪除一個客戶 // 預設情況下(即都不配置級聯刪除的情況下),將外來鍵置為null,刪除資料記錄 // 執行完畢後發現數據庫中OID為1的customer被刪除,customer有關的所有訂單都沒有被刪除,但是這些訂單指向被刪除customer主鍵的外來鍵都被置為null public void demo6() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 刪除方式有兩種 // 但當涉及到物件關聯關係時,只使用先查詢再刪除的情況 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); tx.commit(); session.close(); } @Test // 級聯刪除:刪除客戶的時候級聯刪除訂單 // 在Customer.hbm.xml的<set>標籤上配置級聯刪除的屬性cascade="delete" public void demo7() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 級聯刪除:先查詢再刪除的方式 Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); tx.commit(); session.close(); } @Test // 級聯刪除:刪除訂單的時候,級聯刪除客戶 // 在Order.hbm.xml的<many-to-one>標籤上設定級聯刪除屬性cascade="delete" public void demo8() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Order order = (Order) session.get(Order.class, 1); session.delete(order); tx.commit(); session.close(); } @Test // 孤兒刪除 // 在Customer.hbm.xml中<set>上配置屬性cascade="delete-orphan" // 如果預設情況下 // 即不配置級聯孤兒刪除,一的一方(Customer)從集合中移除了若干的多的一方,並不會刪除被移除的物件,只是將指向它的外來鍵置為null而已 // 一旦在對應集合上配置了級聯孤兒刪除,當從集合中移除物件時,外來鍵置為了null Hibernate會查詢外來鍵為null的多的一方 並將其刪除 public void demo9() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 讓1號客戶和1號訂單解除關係 Customer customer = (Customer) session.get(Customer.class, 1); Order order = (Order) session.get(Order.class, 1); customer.getOrders().remove(order); tx.commit(); session.close(); } @Test // 雙向維護:自動更新資料庫,產生多餘的SQL // 雙方預設都有外來鍵的維護能力.必須讓其中的一方放棄外來鍵的維護權(一般的情況下都是一的一方放棄) // Hibernate: update orders set addr=?, cno=? where oid=? // Hibernate: update orders set cno=? where oid=? public void demo10() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 讓1號客戶和1號訂單解除關係 Customer customer = (Customer) session.get(Customer.class, 1); Order order = (Order) session.get(Order.class, 2); customer.getOrders().add(order); order.setCustomer(customer); tx.commit(); session.close(); } @Test // 區分cascade和inverse // 在Customer.hbm.xml中的<set>上配置cascade="save-update" inverse="true" public void demo11() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setCname("張三"); Order order = new Order(); order.setAddr("西三旗"); customer.getOrders().add(order); // 客戶是否存到資料庫:存 // 訂單是否存到資料庫:存 cascade="save-update".外來鍵是null. session.save(customer); tx.commit(); session.close(); } }