Hibernate中List和Iterate的區別
Hibernate在國內沒有國外那麼火,國內的ORM框架幾乎被Mybatis霸佔,因爲Hibernate的底層採用了大量的反射機制與緩存機制,所以對很多的地方都需要進行調優,而Mybatis的操作幾乎是傻瓜式。Hibernate有時候會因一點點配置的差異會導致項目響應出現極大的反差,今天我們就來說一下Hibernate中Query的兩個獲取對象集合的方法
Query中有兩個獲取對象集合的方法分別爲 List 和 Iterate
List和Iterate的不同
List 和 Iterate 的不同主要是在一對多和多對一的時候體現出來的。
1、獲取的方式不同
// List的獲取方式
List<Invitation> list = query.list();
// Iterator的獲取方式
Iterator<Invitation> it = query.iterate();
2、List 只是查詢一級緩存,而Iterate還會查詢二級緩存
3、List方法返回的對象都是實體對象,而Iterator返回的是代理對象
4、session中的List第二次發出請求,仍會到數據庫査詢,而Iterate 第二次,首先找session 級緩存
List和Iterate的利與弊
List()方法在執行時,現在一級緩存中找,沒有再立馬到數據庫中查詢所需要的數據。對於List()方式的查詢通常只會執行一條SQL語句,List()方法會一次取出所有的結果集對象,以及對象屬性多對一的屬性數據,就是會依據查詢的結果初始化所有的結果集對象(多對一或者一對多)。如果在結果集的數據非常龐大的時候,就會佔據大量的內存,甚至會導致內存的溢出。
Iterator()方法則是先執行得到對象ID的查詢,然後在根據每個ID值去取得所要查詢的對象。而對於iterator()方法的查詢則可能需要執行N+1條SQL語句(N爲結果集中的記錄數),Iterator()方法在執行時不會一次初始化所有的對象,而是根據對結果集的訪問情況來初始化對象,如果你需要使用這個對象中的對象值,那麼它纔會到數據庫中查詢,而且一次在訪問中可以控制緩存中對象的數量,以避免佔用過多的緩存,導致內存溢出情況的發生。
實際調試的數據
測試環境:IDEA、Hibernate 5.4.10.Final、JUNIT 4.0、MySQL 8.0
list獲取數據的調試記錄
測試代碼:
@Test
public void testGetList() {
Session session = sf.openSession();
String hql = "from Invitation";
// list()方法在執行時,直接運行查詢結果所需要的查詢語句。
// 對於list()方式的查詢通常只會執行一個SQL語句
// list()方法會一次取出所有的結果集對象,而且他會依據查詢的結果初始化所有的結果集對象。
// 如果在結果集非常龐大的時候會佔據非常多的內存,甚至會造成內存溢出的情況發生。
Query<Invitation> query = session.createQuery(hql, Invitation.class);
List<Invitation> list = query.list();
for (Invitation l : list) {
System.out.println(l);
}
session.close();
}
Iterate的調試記錄
測試代碼:
@Test
public void testGetIterate() {
Session session = sf.openSession();
// HQL 語句
String hql = "from Invitation";
// 獲取Query對象
// iterator()方法則是先執行得到對象ID的查詢,然後在根據每個ID值去取得所要查詢的對象。
// 而對於iterator()方法的查詢則可能需要執行N+1條SQL語句(N爲結果集中的記錄數).
// iterator()方法在執行時不會一次初始化所有的對象,而是根據對結果集的訪問情況來初始化對象。
// 一次在訪問中可以控制緩存中對象的數量,以避免佔用過多的緩存,導致內存溢出情況的發生。
Query<Invitation> query = session.createQuery(hql, Invitation.class);
Iterator<Invitation> iterate = query.iterate();
Invitation invitation;
while (iterate.hasNext()) {
System.out.println("暫時沒有往數據庫中查詢數據");
invitation = iterate.next();
System.out.println(invitation);
}
session.close();
}