概述:
Hibernate是一個持久層框架,經常訪問物理數據庫。爲了降低應用程序對物理數據源訪問的頻次,從
而提高應用程序的運行性能,緩存的合理使用就尤爲重要。緩存內的數據是對物理數據源中的數據的複製,
應用程序在運行時從緩存讀寫數據,在特定的時刻或事件會同步緩存和物理數據源的數據。
一級和二級緩存:
應用原理:
當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩
存,那麼從二級緩存中查;如果都查不到,再查詢數據庫,把結果按照ID放入到緩存刪除、更新、增加數據
的時候,同時更新緩存。
一級緩存的應用:
當session對象調用save()方法保存一個對象後,該對象會被放入到session的緩存中。get()和
load()。當session對象調用get()或load()方法從數據庫取出一個對象後,該對象也會被放入到session的緩
存中。使用HQL和QBC等從數據庫中查詢數據。
<span style="font-size:18px;">public class Client
{
public static void main(String[] args)
{
Session session =HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try
{
/*開啓一個事務*/
tx =session.beginTransaction();
/*從數據庫中獲取id="001"的Person對象*/
Person person= (Person )session.get(Person .class,"001");
System.out.println("person.getUsername is"+person.getUsername());
/*事務提交*/
tx.commit();
System.out.println("-------------------------------------");
/*開啓一個新事務*/
tx =session.beginTransaction();
/*從數據庫中獲取id="402881e534fa5a440134fa5a45340002"的Customer對象*/
Person person1= (Person )session.get(Person .class,"001");
System.out.println("person1.getUsername is"+person1.getUsername());
/*事務提交*/
tx.commit();
System.out.println("-------------------------------------");
/*比較兩個get()方法獲取的對象是否是同一個對象*/
System.out.println("person== person1result is "+(person==person1));
}
catch (Exceptione)
{
if(tx!=null)
{
tx.rollback();
}
}
finally
{
session.close();
}
}
}</span>
結果:
Hibernate:
select
person0_.id asid0_0_,
person0_.username asusername0_0_,
person0_.balance asbalance0_0_
from
person person0_
where
person0_.id=?
person.getUsernameislisi
-------------------------------------
person.getUsernameislisi
-------------------------------------
person== person1result is true
結果中只包含了一條SELECTSQL語句,而且person==person1 result istrue說明兩個取出來的對象是
同一個對象。其原理是:第一次調用get()方法,Hibernate先檢索緩存中是否有該查找對象,發現沒有,
Hibernate發送SELECT語句到數據庫中取出相應的對象,然後將該對象放入緩存中,以便下次使用,第二次調
用get()方法,Hibernate先檢索緩存中是否有該查找對象,發現正好有該查找對象,就從緩存中取出來,不
再去數據庫中檢索。
總結:
Hibernate 的緩存只從下面兩個方面發生作用 :1.通過主鍵值加載對象 2.延遲加載 。通過主鍵值
加載就會存在N+1問題,我們將在下篇文章介紹通過二級緩存解決N+1問題。而延遲加載實現要解決兩個問
題:
1.正常關閉連接和確保請求中訪問的是同一個session。
2.http請求結束後正確的關閉session(過濾器實現了session的正常關閉),延遲加載必須保證是同一個
session(session綁定在ThreadLocal)。