深入了解Hibernate的緩存使用


Hibernate緩存

      緩存是計算機領域的概念,它介於應用程序和永久性數據存儲源(如在硬盤上的文件或者數據庫)之間,其作用是降低應用程序

直接讀寫永久性數據存儲源的頻率,從而提高應用的運行性能。緩存中的數據是數據存儲源中數據的復制,應用程序在運行時直接

讀寫緩存中的數據,只在某些特定時刻按照緩存中的數據來同步更新數據存儲源。

      緩存的物理介質通常是內存,而永久性數據存儲源的物理介質通常是硬盤或磁盤,應用程序讀寫內存的速度顯然比讀寫硬盤的速度

快。如果緩存中存放的數據量非常大,也會用硬盤作為緩存的物理介質。

Hibernate緩存一般分為3類:

(1)一級緩存。Session緩存稱為一級緩存。由於Session對象的生命周期通常對應一個數據庫事務,因此它的緩存是事務范圍的緩存。

一級緩存是必需的,Session默認帶有,而且不能卸載。在一級緩存中,持久化類的每個實例都具有唯一的OID。

(2)二級緩存。SessionFactory緩存分為內置緩存和外置緩存。內置緩存是Hibernate自帶的,不可拆卸,是只讀緩存,用來存放映射

元數據和預定義SQL語句。外置緩存是一個可配置的緩存插件,默認SessionFactory不會啟用這個緩存插件。外置緩存中的數據是數據庫

數據的復制。SessionFactory對象的生命周期和應用程序的整個進程對應。二級緩存是可選的,可以在每個類或每個集合的粒度上配置二

級緩存。

(3)查詢緩存。它是Hibernate為查詢結果提供的,依賴於二級緩存。

緩存的作用分為3類

(1)事務范圍。每個事務都有自己的緩存,緩存內數據不會被多個事務並發訪問。例如hibernate的一級緩存,事務是不能跨多個Session的,Session內

數據只能被當前事務訪問,因此它屬於事務范圍的緩存。

(2)進程范圍。進程內的所有事物共享緩存,進程結束,緩存結束生命周期,例如hibernate的二級緩存,SessionFactory對象的生命周期對應應用程序的

整個進程,因此它屬於進程范圍的緩存。

(3)集群范圍。緩存被一個或多個機器上的多個進程共享。Hibernate的二級緩存也可以作為集群范圍的緩存。

一級緩存:

    一級緩存的生命周期和session的生命周期一致,當前session一旦關閉,一級緩存就消失了,因此一級緩存也叫session級的緩存或事務級緩存,一級緩存只存實體對象,它不會緩存一般的對象屬性(查詢緩存可以),即當獲得對象后,就將該對象緩存起來,如果在同一session中再去獲取這個對象時,它會先判斷在緩存中有沒有該對象的id,如果有則直接從緩存中獲取此對象,反之才去數據庫中取,取的同時再將此對象作為一級緩存處理。

       
 

內存  dept對象   內存地址:001

 

 deptNo

 deptName

 

 

 
   

一級緩存

 

Key:1

Value:引用  001

 

 
 

 

 

 

 

 

 

 

 

以下方法支持一級緩存:

* get() 
    * load() 
    * iterate(查詢實體對象) 
其中 Query 和Criteria的list() 只會緩存,但不會使用緩存(除非結合查詢緩存)。

 二級緩存:

開發中的用途沒有面試帶來作用大。

二級緩存是進程(N個事務)或集群范圍內的緩存,可以被所有的Session共享,在多個事務之間共享

二級緩存是可配置的插件

 配置二級緩存的步驟:

 *1.引入如下jar包。

      ehcache-1.2.3.jar  核心庫

      backport-util-concurrent.jar 

      commons-logging.jar

   *2.配置Hibernate.cfg.xml開啟二級緩存

   <property name="hibernate.cache.use_second_level_cache">true</property>

  *3.配置二級緩存的供應商

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

  *4.指定使用二級緩存的類

       方案一:在*.hbm.xml中配置

       在<class>元素的子元素下添加chche子節點,但該配置僅會緩存對象的簡單屬性,若希望緩存集合屬性中的元素,必須在set元素中添加<cache>子元素

      <class name="Student" table="STUDENT">

       <cache usage="read-write"/>

方案二:在大配置文件(hibernate.cfg.xml)中配置

位置有限定

Multiple annotations found at this line:

     - The content of element type "session-factory" must match "(property*,mapping*,(class-cache|collection-

      cache)*,event*,listener*)".

   - Start tag of element <session-factory>

     <class-cache   usage="read-write" class="cn.happy.entity.Student"/>

<collection-cache usage="read-write" collection=""/>

*5.在src下添加ehcache.xml文件,從etc獲取文件即可。

解析 :出現如下錯誤因為沒有添加二級緩存所需jar包

org.hibernate.HibernateException: could not instantiate RegionFactory [org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge]

 

二級緩存分為:

       緩存算法 

       類級別緩存區

       集合級別緩存區

       更新時間戳 

       查詢緩存

 

query 的list()和iterate()區別 (必記)

   解析:

1.返回的類型不一樣,list返回List,iterate返回Iterator,
2.獲取數據的方式不一樣,list會直接查數據庫,iterate會先到數據庫中把id都取出來,然后真正要遍歷某個對象的時候先到緩存中找,如果找不到,以id為條件再發一條sql到數據庫,這樣如果緩存中沒有數據,則查詢數據庫的次數為n+1。
3.iterate會查詢2級緩存,list 只會緩存,但不會使用緩存(除非結合查詢緩存)。
4.list中返回的List中每個對象都是原本的對象,iterate中返回的對象是代理對象

 查詢緩存:

1查詢是數據庫技術中最常用的操作,Hibernate為查詢提供了緩存,用來提高查詢速度,優化查詢性能

相同HQL語句檢索結果的緩存!

2查詢緩存依賴於二級緩存

   查詢緩存是針對普通屬性結果集的緩存,對實體對象的結果集只緩存id(其id不是對象的真正id,可以看成是HQL或者SQL語句,它與查詢的條件相關即where后的條件相關,不同的查詢條件,其緩存的id也不一樣)。查詢緩存的生命周期,當前關聯的表發生修改或是查詢條件改變時,那么查詢緩存生命周期結束,它不受一級緩存和二級緩存生命周期的影響,要想使用查詢緩存需要手動配置如下:

* 在hibernate.cfg.xml文件中啟用查詢緩存,如: 
    <property name="hibernate.cache.use_query_cache">true</property>
    * 在程序中必須手動啟用查詢緩存,如: 
    query.setCacheable(true); 
其中 Query 和Criteria的list() 就可利用到查詢緩存了。

案例:

 //查詢緩存
 @Test public void queryTest(){ Session session = HibernateUtils.currentSession(); Transaction tx=session.beginTransaction(); List<Dept> list = session.createQuery("from Dept").setCacheable(true).list(); System.out.println(list.get(0).getDeptName()); tx.commit(); HibernateUtils.closeSession(); Session session2 = HibernateUtils.currentSession(); Transaction tx2=session2.beginTransaction(); List<Dept> list2 = session2.createQuery("from Dept").setCacheable(true).list(); System.out.println(list.get(0).getDeptName()); tx2.commit(); }

總結:

     不要想當然的以為緩存可以提高性能,僅僅在你能夠駕馭它並且條件合適的情況下才是這樣的。hibernate的二級緩存限制還是比較多的。在不了解原理的情況下亂用,可能會有1+N的問題。不當的使用還可能導致讀出臟數據。 如果受不了hibernate的諸多限制,那么還是自己在應用程序的層面上做緩存吧。 

     在越高的層面上做緩存,效果就會越好。就好像盡管磁盤有緩存,數據庫還是要實現自己的緩存,盡管數據庫有緩存,咱們的應用程序還是要做緩存。因為底層的緩存它並不知道高層要用這些數據干什么,只能做的比較通用,而高層可以有針對性的實現緩存,所以在更高的級別上做緩存,效果也要好些吧。

      緩存是位於應用程序與物理數據源之間,用於臨時存放復制數據的內存區域,目的是為了減少應用程序對物理數據源訪問的次數,從而提高應用程序的運行性能. 
    Hibernate在查詢數據時,首先到緩存中去查找,如果找到就直接使用,找不到的時候就會從物理數據源中檢索,所以,把頻繁使用的數據加載到緩存區后,就可以大大減少應用程序對物理數據源的訪問,使得程序的運行性能明顯的提升.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM