溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

hibernate查詢緩存詳細分析

發(fā)布時間:2020-09-09 19:20:08 來源:腳本之家 閱讀:143 作者:動力節(jié)點 欄目:編程語言

 一、查詢緩存配置

1、在hibernate.cfg.xml中加入查詢緩存的策略,  <propertyname="hibernate.cache.use_query_cache">true</property>      啟用查詢緩存的策略,默認是false。 

二、關閉二級緩存,采用query.list()查詢普通屬性

代碼如下所示。

public voidtestCache1() { 
  Session session = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   Listnames = session.createQuery("select s.name from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<names.size(); i++) { 
   Stringname = (String)names.get(i); 
   System.out.println(name); 
   } 
   System.out.println("-------------------------------------------------------"); 
   //不會發(fā)出查詢語句,因為啟用查詢緩存 
   names= session.createQuery("select s.name from Student s") 
      .setCacheable(true) 
      .list(); 
   for (int i=0;i<names.size(); i++) { 
   Stringname = (String)names.get(i); 
   System.out.println(name); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
 } 

我們可以看到控制臺輸出語句,僅輸出一次:Hibernate: select student0_.name as col_0_0_ fromt_student student0_ 

由此可知,我們開啟了查詢緩存,第一次進行查詢的時候,已經(jīng)把結果放到querycache中,當?shù)诙卧俅巫龀鱿嗤牟樵兊臅r候,就不再向數(shù)據(jù)庫發(fā)重復的sql語句了。

三、關閉二級緩存,啟用查詢緩存,采用query.list()查詢普通屬性

代碼就如下所示。

public voidtestCache2() { 
  Sessionsession = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   Listnames = session.createQuery("select s.name from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<names.size(); i++) { 
   Stringname = (String)names.get(i); 
   System.out.println(name); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  System.out.println("-------------------------------------------------------"); 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   //不會發(fā)出查詢語句,因為查詢緩存和session的生命周期沒有關系 
   Listnames = session.createQuery("select s.name from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<names.size(); i++) { 
   Stringname = (String)names.get(i); 
   System.out.println(name); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  }   
 }  

運行結果如下所示。

控制臺打印結果:

select student0_.name as col_0_0_ fromt_student student0_
班級0的學生0
班級0的學生1
班級0的學生2
班級0的學生3
班級0的學生4
班級0的學生5…

我們可以看出,同樣,只打印一次查詢語句,如果沒有開啟查詢緩存的話,并且關閉二級緩存的情況下,還會去數(shù)據(jù)庫再查詢一遍,而我們的程序中沒有再去重復的去數(shù)據(jù)庫中查詢的原因是,當開啟query緩存的時候,查詢緩存的生命周期與session無關。

四、關閉二級緩存,開啟查詢,采用query.iterate()查詢普通屬性

代碼如下所示。

public voidtestCache3() { 
  Sessionsession = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   Iteratoriter = session.createQuery("select s.name from Student s") 
       .setCacheable(true) 
       .iterate(); 
   while(iter.hasNext()){ 
   Stringname = (String)iter.next(); 
   System.out.println(name); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  System.out.println("-------------------------------------------------------"); 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   //會發(fā)出查詢語句,query.iterate()查詢普通屬性它不會使用查詢緩存 
   //查詢緩存只對query.list()起作用 
   Iteratoriter = session.createQuery("select s.name from Student s") 
      .setCacheable(true) 
      .iterate(); 
   while(iter.hasNext()){ 
   Stringname = (String)iter.next(); 
   System.out.println(name); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  
 } 

顯控制臺顯示結果打印了兩次sql語句。

-------------------------------------------------------

Hibernate: select student0_.name as col_0_0_from t_student student0_

根據(jù)這樣的結果我們發(fā)現(xiàn),quer.iterate()查詢普通屬性它是不會使用查詢緩存,查詢緩存只對query.list()起作用。

五、關閉二級緩存,關閉查詢緩存,采用query.list()查詢實體

代碼如下所示。

public voidtestCache4() { 
  Sessionsession = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   List students =session.createQuery("select s from Student s") 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  System.out.println("-------------------------------------------------------"); 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   //會發(fā)出查詢語句,默認query.list()每次執(zhí)行都會發(fā)出查詢語句 
   List students =session.createQuery("select s from Student s") 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
 } 

   顯示結果如下所示。

控制臺上打印兩次sql語句。

Hibernate:select student0_.id as id0_, student0_.name as name0_, student0_.classesid asclassesid0_ from t_student student0_

班級0的學生0
班級0的學生1
班級0的學生2
班級0的學生3
班級0的學生4

由此可知,不開啟查詢緩存,默認query.list每次執(zhí)行都會發(fā)出查詢語句。

六、關閉二級緩存,開啟查詢緩存,采用query.list()查詢實體

代碼如下所示。

Session session = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   Liststudents = session.createQuery("select s from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  System.out.println("-------------------------------------------------------"); 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   
   //會發(fā)出n條查詢語句,因為開啟了查詢緩存,關閉了二級緩存,那么查詢緩存就會緩存實體對象的id 
   //第二次執(zhí)行query.list(),將查詢緩存中的id依次取出,分別到一級緩存和二級緩存中查詢相應的實體 
   //對象,如果存在就使用緩存中的實體對象,否則根據(jù)id發(fā)出查詢學生的語句 
   Liststudents = session.createQuery("select s from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 

控制臺打印sql如下圖所示。

hibernate查詢緩存詳細分析

在第一次查詢的時候,發(fā)出一條sql語句查詢出結果,因為我們開啟了查詢緩存,會把第一次查詢出的實體結果集的id放到查詢緩存中,第二次再次執(zhí)行query.list()的時候,會把id拿出來,到相應的緩存去找,因為是跨session,在二級緩存中找不到,所以每次都會發(fā)出查詢語句,二級緩存中不存在,有多少個id就會發(fā)出查詢語句多少次。 

七、開啟二級緩存,開啟查詢緩存,采用query.list()查詢實體

代碼如下所示。

/** 
 * 開啟查詢,開啟二級緩存,采用query.list()查詢實體 
 * 
 * 在兩個session中發(fā)query.list()查詢 
 */ 
 public voidtestCache6() { 
  Sessionsession = null; 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   Liststudents = session.createQuery("select s from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
   session.getTransaction().commit(); 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
  System.out.println("-------------------------------------------------------"); 
  try { 
   session= HibernateUtils.getSession(); 
   session.beginTransaction(); 
   
   //不再發(fā)出查詢語句,因為配置了二級緩存和查詢緩存 
   Liststudents = session.createQuery("select s from Student s") 
       .setCacheable(true) 
       .list(); 
   for (int i=0;i<students.size(); i++) { 
   Studentstudnet = (Student)students.get(i); 
   System.out.println(studnet.getName()); 
   } 
  }catch(Exceptione) { 
   e.printStackTrace(); 
   session.getTransaction().rollback(); 
  }finally { 
   HibernateUtils.closeSession(session); 
  } 
 } 

結果如下所示

Hibernate: select student0_.id as id0_,student0_.name as name0_, student0_.classesid as classesid0_ from t_studentstudent0_

只發(fā)出一次sql請求,當我們第一次執(zhí)行query.list()會放到二級緩存中,和query緩存中。當我們第一次執(zhí)行查詢時,會找到相應的id到緩存中查找,在二級緩存中存在,則直接從二級緩存中取出數(shù)據(jù),不再向數(shù)據(jù)庫中發(fā)出sql語句。

八、查詢緩存總結

查詢緩存是緩存普通屬性結果集的,對實體對象的結果集會緩存id。查詢緩存的生命周期,當關聯(lián)的表發(fā)生修改時,查詢緩存的生命周期結束。

而開啟緩存的時候,我們就要去維護緩存,如果緩存和內存中的數(shù)據(jù)不一致的話,和數(shù)據(jù)不同步,可能給用戶顯示的是臟數(shù)據(jù)了。所以根據(jù)需要使用緩存機制。

總結

以上所述是小編給大家介紹的hibernate查詢緩存詳細分析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網(wǎng)站的支持!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI