【Hibernate筆記整理九】抓取策略

版權聲明:本文爲 小異常 原創文章,非商用自由轉載-保持署名-註明出處,謝謝!
本文網址:https://blog.csdn.net/sun8112133/article/details/106151655







抓取策略 這一塊,一般情況下,在開發中用不到,使用默認值即可,但是面試的時候可能會問。


一、延遲加載

延遲加載 我們也叫 lazy(也就是懶加載)。意思是執行到該行代碼的時候,不會發送語句去進行查詢,在真正使用這個對象時,纔會發送 SQL 語句進行查詢,這樣做很大程度上提高了程序的執行效率。

1、分類

1)類級別

類級別 的延遲加載是指通過 load() 方法查詢某個對象時,是否採用延遲。

session.load(Customer.class, 1L);

配置類級別的延遲加載通過映射文件中的 <class> 標籤上的 lazy 屬性進行配置。如果讓 lazy 失效,有三種辦法:
1. 將 lazy 設置爲 false
2. 將持久化類使用 final 修飾;
3. Hibernate.initialize():初始化方法 Hibernate.initialize(customer);

@Test
/*
 * 類級別的延遲加載
 * 	在 <class> 的標籤上配置的 lazy
 */
public void demo1() {
	Session session = HibernateUtils.getCurrentSession();
	Transaction tx = session.beginTransaction();

	Customer customer = session.load(Customer.class, 1L); // 獲得的是代理對象
	Hibernate.initialize(customer);
	System.out.println(customer);

	tx.commit();
}

2)關聯級別

關聯級別 的延遲加載是指在查詢到某個對象時,當查詢其關聯對象時,是否採用延遲加載。

Customer customer = session.get(Customer.class, 1L);
customer.getLinkMan();   // 通過客戶獲得聯繫人的時候,聯繫人對象是否採用了延遲加載,稱爲是關聯級別的延遲


二、抓取策略

通過一個對象抓取到關聯對象需要發送 SQL 語句,而 SQL 語句何時發送,發送什麼樣格式得通過 fetchlazy 進行配置。抓取策略 往往和 關聯級別的延遲加載 一起使用來優化 SQL 語句。

1、 上的 fetch 和 lazy

1)fetch

抓取策略,控制 SQL 語句格式。

  • select:默認值,發送普通的 select 語句,查詢關聯對象;
  • join:發送一條迫切左外連接查詢關聯對象;
  • subselect:發送一條子查詢查詢其關聯對象。

2)lazy

延遲加載,控制查詢關聯對象時,是否採用延遲。

  • true:默認值;
  • false:查詢關聯對象時,不採用延遲加載;
  • extra:極其懶惰。

在實際開發中,一般都採用默認值。如果有特殊的需求,可能需要配置 join


3)測試

/**
 * 在 <set> 上的 fetch 和 lazy
 * @author Administrator
 *
 */
public class HibernateDemo1 {
	@Test
	/*
	 * 默認情況  fetch="select" lazy="true"
	 */
	public void demo1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 查詢 1 號客戶
		Customer customer = session.get(Customer.class, 1L);   // 發送一條查詢客戶的 SQL 
		System.out.println(customer.getCust_name());
		// 查看 1 號客戶的每個聯繫人的信息
		for (LinkMan linkMan : customer.getLinkMans()) {   // 發送一條根據客戶 ID 查詢聯繫人的 SQL
			System.out.println(linkMan.getLkm_name());
		}
		
		tx.commit();
	}
	
	@Test
	/*
	 * 設置  fetch="select" lazy="false"
	 */
	public void demo2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 查詢 1 號客戶
		Customer customer = session.get(Customer.class, 1L);   // 發送兩條SQL語句:查詢客戶的名稱,查詢客戶關聯聯繫人 
		System.out.println(customer.getCust_name());
		// 查看 1 號客戶的每個聯繫人的信息
		for (LinkMan linkMan : customer.getLinkMans()) {
			System.out.println(linkMan.getLkm_name());
		}
		
		tx.commit();
	}
	
	@Test
	/*
	 * 設置  fetch="select" lazy="extra"
	 */
	public void demo3() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 查詢 1 號客戶
		Customer customer = session.get(Customer.class, 1L);   // 發送一條查詢1號客戶的 SQL語句
		System.out.println(customer.getCust_name());
		// 查看 1 號客戶的聯繫人的個數
		System.out.println(customer.getLinkMans().size());  // 發送一條 select count() from ....
		
		tx.commit();
	}
	
	@Test
	/*
	 * 設置  fetch="join" lazy=失效
	 */
	public void demo4() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		// 查詢 1 號客戶
		Customer customer = session.get(Customer.class, 1L);   // 發送一條迫切左外連接查詢記錄
		System.out.println(customer.getCust_name());
		// 查看 1 號客戶的聯繫人的個數
		System.out.println(customer.getLinkMans().size());   // 不發送
		
		tx.commit();
	}
	
	@SuppressWarnings("unchecked")
	@Test
	/*
	 * 設置  fetch="subselect" lazy="true"
	 */
	public void demo5() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		List<Customer> list = session.createQuery("from Customer").list();   // 發送查詢所有客戶的SQL
		for (Customer customer : list) {
			System.out.println(customer.getCust_name());
			System.out.println(customer.getLinkMans().size());   // 發送一條子查詢
		}
		
		tx.commit();
	}
	
	@SuppressWarnings("unchecked")
	@Test
	/*
	 * 設置  fetch="subselect" lazy="false"
	 */
	public void demo6() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		List<Customer> list = session.createQuery("from Customer").list();   // 發送查詢所有客戶的SQL,發送一條子查詢
		for (Customer customer : list) {
			System.out.println(customer.getCust_name());
			System.out.println(customer.getLinkMans().size());
		}
		
		tx.commit();
	}
	
}

2、 上的 fetch 和 lazy

1)fetch

抓取策略,控制 SQL 語句格式。

  • select:默認值,發送普通的 select 語句,查詢關聯對象;
  • join:發送一條迫切左外連接查詢關聯對象。

2)lazy

延遲加載,控制查詢關聯對象時,是否採用延遲。

  • proxy:默認值,取決於另一端的 <class> 上的 lazy 的值;
  • false:查詢關聯對象時,不採用延遲加載;
  • no-proxy:(不會使用)。

在實際開發中,一般都採用默認值。如果有特殊的需求,可能需要配置 join


3)測試

/**
 * many-to-one 上的 fetch 和 lazy 測試
 * @author Administrator
 *
 */
public class HibernateDemo2 {

	@Test
	/*
	 * 默認值  fetch="select" lazy="proxy"
	 */
	public void demo1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		LinkMan linkMan = session.get(LinkMan.class, 1L);   // 發送一條查詢聯繫人語句
		System.out.println(linkMan.getLkm_name());
		System.out.println(linkMan.getCustomer().getCust_name());   // 發送一條 select 語句查詢聯繫人所關聯的客戶
		
		tx.commit();
	}
	
	@Test
	/*
	 * 默認值  fetch="select" lazy="false"
	 */
	public void demo2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		LinkMan linkMan = session.get(LinkMan.class, 1L);   // 發送一條查詢聯繫人語句,發送一條 select 語句查詢聯繫人所關聯的客戶
		System.out.println(linkMan.getLkm_name());
		System.out.println(linkMan.getCustomer().getCust_name());
		
		tx.commit();
	}
	
	@Test
	/*
	 * 默認值  fetch="join" lazy=失效
	 */
	public void demo3() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		LinkMan linkMan = session.get(LinkMan.class, 1L);   // 發送一條迫切左外連接查詢聯繫人所關聯的客戶。
		System.out.println(linkMan.getLkm_name());
		System.out.println(linkMan.getCustomer().getCust_name());
		
		tx.commit();
	}
	
}


三、批量抓取

批量抓取 就是一批關聯對象一起抓取,通過映射文件中 <set> 標籤上的 batch-size 屬性進行配置。

/**
 * 批量抓取
 * @author Administrator
 *
 */
public class HibernateDemo3 {

	@SuppressWarnings("unchecked")
	@Test
	/*
	 * 獲取客戶的時候,批量抓取聯繫人
	 * 		在 Customer.hbm.xml 中 <set> 上配置 batch-size
	 */
	public void demo1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		List<Customer> list = session.createQuery("from Customer").list();
		for (Customer customer : list) {
			System.out.println(customer.getCust_name());
			for (LinkMan linkMan : customer.getLinkMans()) {
				System.out.println(linkMan.getLkm_name());
			}
		}
		
		tx.commit();
	}
	
	@SuppressWarnings("unchecked")
	@Test
	/*
	 * 獲取聯繫人的時候,批量抓取客戶
	 * 		在 Customer.hbm.xml 中 <class> 上配置 batch-size
	 */
	public void demo2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tx = session.beginTransaction();
		
		List<LinkMan> list = session.createQuery("from LinkMan").list();
		for (LinkMan linkMan : list) {
			System.out.println(linkMan.getLkm_name());
			System.out.println(linkMan.getCustomer().getCust_name());
		}
		
		tx.commit();
	}
	
}


博客中若有不恰當的地方,請您一定要告訴我。前路崎嶇,望我們可以互相幫助,並肩前行!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章