版權聲明:本文爲 小異常 原創文章,非商用自由轉載-保持署名-註明出處,謝謝!
本文網址: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 語句何時發送,發送什麼樣格式得通過
fetch
和lazy
進行配置。抓取策略 往往和 關聯級別的延遲加載 一起使用來優化 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();
}
}