package cn.bdqn.test; import java.util.Iterator; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; import cn.bdqn.bean.Student; import cn.bdqn.util.HibernateSessionUtil; public class StudentTest { Session session=null; Transaction transaction=null; @Before public void before(){ //getCurrentSession 必須在事務下運行 session=HibernateSessionUtil.getCurrentSession(); transaction=session.beginTransaction(); //開啓事務 } /** * HQL: hibernate查詢語言! * * 執行hql的步驟: * 01.獲取session對象 * 02.編寫hql語句 使用面向對象的思想! hql中只有類 和屬性 !不存在 表和字段 * 03.經過session.createQuery(String hql) 建立Query對象 * 05.執行對應的查詢 */ /** * list查詢全部: * 01.會當即產生一條select語句! * select查詢出來的全部數據,都會被session管理!保存在緩存中! * 02.清空或者不清空session緩存中的數據 * 03.再次執行查詢的時候 都會執行一條select語句! */ @Test public void testList(){ //Student 必須大寫 由於是 類名 String hql="from Student"; //建立Query對象 Query query = session.createQuery(hql); //執行對應的查詢 System.out.println("*************"); List<Student> list = query.list(); System.out.println("*************"); for (Student student : list) { System.out.println(student); } //清空緩存 //session.clear(); //再次執行對應的查詢 list = query.list(); for (Student student : list) { System.out.println(student); } } /** * Iterator:查詢全部 * * 測試環境:數據庫中有5條數據 * * 產生的結果: * 01.6條select語句 * 02.第一條 是查詢數據庫表中全部的id,這條語句是query.iterate()產生的! * 03.其餘的5條select語句 都是根據id進行查詢!都是在.next()產生的! */ @Test public void testIterator(){ String hql="from Student"; Query query = session.createQuery(hql); System.out.println("*************"); Iterator<Student> iterate = query.iterate(); System.out.println("*************"); while (iterate.hasNext()) { System.out.println("*************"); Student stu = iterate.next(); System.out.println("*************"); System.out.println(stu); } } /** * 01.iterate在有緩存的狀況下,若是緩存中有查詢的全部數據!只會執行一條sql語句! * 這條sql就是查詢全部的id! * 02.若是緩存中有2條數據! id =1 id=2 * 咱們查詢了全部的5條數據! * 這時候會產生多少條sql? 3+1 */ @Test public void testIterator2(){ String hql="from Student"; Query query = session.createQuery(hql); Iterator<Student> iterate = query.iterate(); while (iterate.hasNext()) { Student stu = iterate.next(); System.out.println(stu); } System.out.println("********************"); //再次查詢 沒有清空緩存 iterate = query.iterate(); while (iterate.hasNext()) { Student stu = iterate.next(); System.out.println(stu); } } /** * 測試環境: * 緩存中有兩條數據 * 結果: * 01.get確定產生sql * 02.iterate遍歷的時候 先去緩存中獲取已經存在的數據! 就會減小2次查詢! */ @Test public void testIterator21(){ //獲取id爲1的student對象 Student student1= (Student) session.get(Student.class, 1); // 產生1條 Student student2 = (Student) session.get(Student.class, 2); // 產生1條 System.out.println("*************************"); String hql="from Student"; Query query = session.createQuery(hql); Iterator<Student> iterate = query.iterate(); // 產生1條 while (iterate.hasNext()) { Student stu = iterate.next();// 產生4條 System.out.println(stu); } } /** *iterate在沒有緩存的狀況下 會執行N+1條數據! *N:指的是數據數量! *1:查詢全部的ID! */ @Test public void testIterator3(){ String hql="from Student"; Query query = session.createQuery(hql); Iterator<Student> iterate = query.iterate(); while (iterate.hasNext()) { Student stu = iterate.next(); System.out.println(stu); } System.out.println("********************"); //再次查詢 清空緩存 session.clear(); iterate = query.iterate(); while (iterate.hasNext()) { Student stu = iterate.next(); System.out.println(stu); } }
}
/** Query接口中的list()和iterate()均可以執行查詢操做,
而iterate()可以利用延遲加載和緩存的機制提升查詢性能!iterate()查詢時,
僅查詢ID字段以節省資源。須要使用數據時,再根據ID字段到緩存中檢索匹配的實例!
若是存在就直接使用!只有當緩存中沒有須要的數據時,iterate()纔會執行select語句
!根據ID字段到數據庫中查詢!iterate()更適用於查詢對象開啓二級緩存的狀況! */
list 和 iterato r的區別:
(1) 從上面的執行結果能夠看出獲取的方式不同java
List的獲取方式爲:List<Customers> list = query.list();sql
Iterator的獲取方式:Iterator<Customers> it = query.iterate();數據庫
(2)從執行結果能夠看出list輸出一條語句,而iterator輸出的是兩條sql語句,咱們可想一下,爲何會輸出這樣的效果?緩存
由於他們獲取數據的方式不同,list()會直接查詢數據庫,iterator()會先到數據庫中把id都取出來,而後真正要遍歷某個對象的時候先到緩存中找,若是找不到,以id爲條件再發一條sql到數據庫,這樣若是緩存中沒有數據,則查詢數據庫的次數爲n+1次session
(3)list只查詢一級緩存,而iterator會從二級緩存中查性能
(4)list方法返回的對象都是實體對象,而iterator返回的是代理對象測試
(5) session中list第二次發出,仍會到數據庫査詢spa
(6) iterate 第二次,首先找session 級緩存hibernate