1. 程式人生 > >JAVAWEB開發之Hibernate詳解(二)——Hibernate的持久化類狀態與轉換、以及一級快取詳解、關聯關係的對映(一對多、多對多、級聯)

JAVAWEB開發之Hibernate詳解(二)——Hibernate的持久化類狀態與轉換、以及一級快取詳解、關聯關係的對映(一對多、多對多、級聯)

package 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();
	}

}
Course