Hibernate的1級、2級Cache管理及EhCache的使用

來源:互聯網
上載者:User

Cache就是緩衝,它往往是提高系統效能的最重要手段,對資料起到一個蓄水池和緩衝的作用。Cache對於大量依賴資料讀取操作的系統而言尤其重要。在大並發量的情況下,如果每次程式都需要向資料庫直接做查詢操作,它們所帶來的效能開銷顯而易見,頻繁的網路傳輸、資料庫磁碟的讀寫操作都會大大降低系統的整體效能。此時,如果能把資料在本地記憶體中保留一個鏡像,下次訪問時只需從記憶體中直接擷取,那麼顯然可以帶來顯著的效能提升。引入Cache機制的痛點是如何保證記憶體中資料的有效性,否則髒資料的出現將會給系統帶來難以預知的嚴重後果。雖然一個設計得很好的應用程式不用Cache也可以表現出讓人接受的效能,但毫無疑問,一些對讀操作要求很高的應用程式可以通過Cache取得更高的效能。對於應用程式,Cache通過記憶體或磁碟儲存了資料庫中當前有關資料狀態,它是一個存於當地的資料備份。Cache位於資料庫和應用程式之間,從資料庫中更新資料,並給程式提供資料。

Hibernate實現了良好的Cache機制,可以藉助Hibernate內部的Cache迅速提高系統資料讀取效能。Hibernate中的Cache可分為兩層:一級Cache和二級Cache。

一級Cache

Session實現了第一級Cache,它屬於事務級資料緩衝。一旦事務結束,這個Cache也隨之失效。一個Session的生命週期對應一個資料庫事務或一個程式事務。

Session-cache保證在一個Session中兩次請求同一個對象時,取得的對象是同一個Java執行個體,有時它可以避免不必要的資料衝突。另外,它還能保證另一些重要的效能。

在對一個對象循環參考時,不至於產生堆疊溢位。

當資料庫事務結束時,對於同一資料庫行,不會產生資料衝突,因為對於資料庫中的一行,至多有一個對象來表示它。

一個事務中可能會有很多個處理單元,在一個處理單元中做的操作都會立即被另外的處理單元得知。

不用刻意去開啟Session-cache,它總是被開啟並且不能被關閉。當使用save()、update()或saveOrUpdate()來儲存資料更改,或通過load()、find()、list()等方法來得到對象時,對象就會被加入到Session-cache。

如果要同步很大數量的對象,這是需要有效地管理Cache,可以用Session的evict()方法從一級Cache中移除對象。例如:

Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction() ;for(int i=0; i<100000 ;i++) {Student stu = new Student();….session.save(stu);}tx.commit();session.close();
 
在儲存50 000個對象時,程式可能拋出OutOfMemoryException異常,因為Hibernate在一級Cache緩衝了新加入資料庫的所有對象。要解決這個問題,首先設定JDBC批處理數量到一個合理的數值(一般是10~20)。在hibernate.properties設定檔中設定如下:
 hibernate.jdbc.batch_size 20
或在hibernate.cfg.xml中設定如下:
<property name=”hibernate.jdbc.batch_size”> 20 </property>
然後在一定的時候提交更改並清空Session的Cache:
 Session session = HibernateUtil.currentSession();Transaction tx = session.beginTransaction() ;for(int i=0; i<100000 ;i++) {Student stu = new Student();….session.save(stu);if(i%20==0) { //每儲存完20個Student對象後,進行以下操作session.flush(); //提交更新session.clear(); //清除Cache,釋放記憶體}}tx.commit();session.close();

 

二級Cache
二級Cache是SessionFactory範圍內的緩衝,所有的Session共用同一個二級Cache。在二級Cache中儲存持久性執行個體的散裝形式的資料。二級Cache的內部是如何?的並不重要,重要的是採用哪種正確的緩衝策略,以及採用哪種Cache Providers。持久化不同的資料需要不同的Cache策略,比如說一些因素將影響到Cache策略選擇:資料的讀/寫比例、資料表是否能被其他的應用程式所訪問等。對於一些讀/寫比例高的資料可以開啟它的緩衝,允許這些資料進入二級緩衝容器有利於系統效能的最佳化;而對於能被其他應用程式訪問的資料對象,最好將此對象的二級Cache選項關閉。

設定Hibernate的二級Cache需要分兩步進行:首先確認使用什麼資料並發策略,然後配置緩衝到期時間和設定Cache提供器。

有4種內建的Hibernate資料並發衝突策略,代表了資料庫隔離等級,如下所示。

transactional:僅在受管理的環境中可用。它保證可重讀的實物隔離等級,可以對讀/寫比例高、很少更新的資料採用這種策略。

read-write:使用timestamp機制維護讀已提交交易隔離等級。可以對讀/寫比例高、很少更新的資料採用這策略。

nonstrict-read-write:不保證Cache和資料庫之間的資料一致性。使用此策略時,應該設定足夠短的緩衝到期時間,否則可能從緩衝中讀出髒資料。當一些資料極少改變,並且當這些資料和資料庫有一部分不一致但影響不大時,可以使用此策略。

read-only:當確保資料永不改變時,可以使用此策略。

確定了Cache策略之後,就要挑選一個合適高效的Cache提供器,它作為外掛程式被Hibernate調用。Hibernate允許使用下述幾種快取區外掛程式。

EhCache:可以在JVM中作為一個簡單進程範圍的緩衝,它可以把緩衝的資料放入記憶體或磁碟,並支援Hibernate中可選用的查詢快取。

OpenSymphony OSCache:和EhCache相似,並且它提供了豐富的緩衝到期策略。
SwarmCache:可作為叢集範圍的緩衝,但不支援查詢快取。
JBossCache:可作為叢集範圍的緩衝,但不支援查詢快取。

上述4種快取區外掛程式的對比情況列於表9-3中。
表9-3  4種快取區外掛程式的對比情況

緩 存 插 件
 支 持 只 讀
 支援非嚴格讀寫
 支 持 讀 寫
 支 持 事 務
 
EhCache
 是
 是
 是
 
 
OSCache
 是
 是
 是
 
 
SwarmCache
 是
 是
 
 
 
JBossCache
 是
 
 
 是
 

它們的提供器列於表9-4中。
表9-4  緩衝策略的提供器

緩 存 插 件
 提供器(Cache Providers)
 
Hashtable(只能測試時使用)
 org.hibernate.cache.HashtableCacheProvider
 
EhCache
 org.hibernate.cache.EhCacheProvider
 
OSCache
 org.hibernate.cache.OSCacheProvider
 
SwarmCache
 org.hibernate.cache.SwarmCacheProvider
 
JBossCache
 org.hibernate.cache.TreeCacheProvider
 

在預設情況下,Hibernate使用EhCache進行JVM層級的緩衝。使用者可以通過設定Hibernate設定檔中的hibernate.cache.provider_class的屬性,指定其他的緩衝策略,該緩衝策略必須實現org.hibernate.cache.CacheProvider介面。

在Hibernate中使用EhCache

EhCache是一個純Java程式,可以在Hibernate中作為一個外掛程式引入。它具有運行速度快、結構簡單、佔用記憶體小、很小的依賴性、支援多CPU伺服器、文檔齊全等特點。

在Hibernate中使用EhCache,需要在hibernate.cfg.xml中設定如下:

<property name=” hibernate.cache.provider_class”>org.hibernate.cache.EhCacheProvider</property>
 
EhCacheProvider類位於hibernate3.jar包中,而不是位於ehcache-1.1.jar包中。EhCache有自己的配置文檔,名為ehcache.xml。在Hibernate3.x中的etc目錄下有ehcache.xml的示範檔案,將其複製應用程式的src目錄下(編譯時間會把ehcache.xml複製到WEB-INF/classess目錄下),對其中的相關值變更以和自己的程式相適合。進行配置後,在ehcache.xml檔案中的全部代碼如下:
  <diskStore path="d:\\cache"/> //設定cache.data檔案的存放位置    <defaultCachemaxElementsInMemory="10000" //緩衝中允許建立的最大對象數eternal="false" //緩衝中對象是否為永久的timeToIdleSeconds="120" //快取資料鈍化時間(即對象在它到期前的空閑時間)timeToLiveSeconds="120" //快取資料存留時間(即對象在它到期前的存留時間)overflowToDisk="true"  //是否啟用磁碟緩衝/>    <cache name="Student"   //使用者自訂的Cache配置maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"overflowToDisk="true"/></ehcache>

此外,還需要在持久化類的對應檔中進行配置。例如,Group(班級)和Student(學生)是一對多的關係,它們對應的資料表分別是t_group和t_student。現在要把Student類的資料進行二級緩衝,這需要在兩個對應檔(Student.hbm.xml和Group.hbm.xml)中都對二級緩衝進行配置。

在Group.hbm.xml中配置二級緩衝如下:

    ……<hibernate-mapping><class name="Group" table="t_group" lazy="false">……<set name="students" cascade="save-update" inverse="true"   <!--關係由Student維護-->lazy="true"><cache usage="read-write"/>  //<!--集合中的資料將被緩衝--><key column="id"/><one-to-many class="Student"/></set></class></hibernate-mapping>……
 
上述檔案雖然在<set>標記中設定了<cache usage="read-write"/>,但Hibernate僅把和Group相關的Student的主鍵id加入到緩衝中,如果希望把整個Student的散裝屬性都加入到二級緩衝中,還需要在Student.hbm.xml檔案的<class>標記中加入<cache>子標記,如下所示:
<class name="Student" table="t_student" ><cache usage="read-write" /> <!--cache標記需跟在class標記後-->……</class>
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.