Hibernate緩存簡介及分類
一、Hibernate緩存簡介 Cache In Hibernate
HIBERNATE中的CACHE有兩級.
一級是在Session范圍內(nèi)的CACHE. 即每個Session有自己的一個CACHE, 當前操作的對象都會被保留在CACHE中. 但是Session關(guān)閉后這個CACHE也就沒有. 可見這級CACHE的生命期是很短的. (使用id進行關(guān)鍵字存儲:緩存的key就是ID,value是POJO)(緩存的是實體對象)
另一級CACHE是在SessionFactory范圍的, 可以被來自同一個SessionFactory的Session共享. 在HIBERNATE的文檔中稱其為SECOND LEVEL CACHE. 顯然后者的優(yōu)勢較明顯, 也比較復合當前的使用環(huán)境. 它可以使用不同的緩存實現(xiàn),如EhCache、JBossCache、OsCache等 (二級緩存是緩存實體對象的)
還有一個類型的CACHE就是QueryCache. 它的作用就是緩存一個Query以及Query返回對象的Identifier以及對象的類型. 有了QueryCache后就可以高效的使用SECOND LEVEL CACHE.
hibernate緩存查詢(hibernate默認是關(guān)閉的)
查詢緩存是針對普通屬性結(jié)果集的緩存
對實體對象的結(jié)果集只緩存id
查詢緩存的生命周期,當前關(guān)聯(lián)的表發(fā)生修改,那么查詢緩存生命周期結(jié)束
查詢緩存的配置和使用:
1. 啟用查詢緩存:在hibernate.cfg.xml中加入:
- < property name=”hibernate.cache.use_query_cache”>true< /property>
2. 在程序中必須手動啟用查詢緩存,如:query.setCacheable(true);
QueryCache用來緩存查詢語句, 及查詢結(jié)果集中對象的Identifier與Type. 當再次使用已緩存的Query時, 就可以通過對象的Identifier與Type在SECOND LEVEL CACHE中查找實際的對象.
對于查詢緩存來說,緩存的key是根據(jù)hql生成的sql,再加上參數(shù),分頁等信息(可以通過日志輸出看到,不過它的輸出不是很可讀,最好改一下它的代碼)。
注:一級緩存也叫session級的緩存或事務(wù)緩存。Hibernate二級緩存也稱為進程級的緩存或SessionFactory級的緩存。二級緩存是全局緩存,它可以被所有的session共享。二級緩存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二級緩存。
二、Hibernate緩存的范圍
Hibernate緩存的范圍分為3類:
1.事務(wù)范圍
事務(wù)范圍的緩存只能被當前事務(wù)訪問,每個事務(wù)都有各自的緩存,緩存內(nèi)的數(shù)據(jù)通常采用相互關(guān)聯(lián)的對象形式.緩存的生命周期依賴于事務(wù)的生命周期,只有當事務(wù)結(jié)束時,緩存的生命周期才會結(jié)束.事務(wù)范圍的緩存使用內(nèi)存作為存儲介質(zhì),一級緩存就屬于事務(wù)范圍.
2.應用范圍
應用程序的緩存可以被應用范圍內(nèi)的所有事務(wù)共享訪問.緩存的生命周期依賴于應用的生命周期,只有當應用結(jié)束時,緩存的生命周期才會結(jié)束.應用范圍的緩存可以使用內(nèi)存或硬盤作為存儲介質(zhì),二級緩存就屬于應用范圍.
3.集群范圍
在集群環(huán)境中,緩存被一個機器或多個機器的進程共享,緩存中的數(shù)據(jù)被復制到集群環(huán)境中的每個進程節(jié)點,進程間通過遠程通信來保證緩存中的數(shù)據(jù)的一致,緩存中的數(shù)據(jù)通常采用對象的松散數(shù)據(jù)形式.
三、Hibernate緩存的方式
有四種,分別為:
CacheConcurrencyStrategy.NONE
CacheConcurrencyStrategy.READ_ONLY,只讀模式,在此模式下,如果對數(shù)據(jù)進行更新操作,會有異常;
CacheConcurrencyStrategy.READ_WRITE,讀寫模式在更新緩存的時候會把緩存里面的數(shù)據(jù)換成一個鎖,其它事務(wù)如果去取相應的緩存數(shù)據(jù),發(fā)現(xiàn)被鎖了,直接就去數(shù)據(jù)庫查詢;
CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,不嚴格的讀寫模式則不會的緩存數(shù)據(jù)加鎖;
CacheConcurrencyStrategy.TRANSACTIONAL,事務(wù)模式指緩存支持事務(wù),當事務(wù)回滾時,緩存也能回滾,只支持JTA環(huán)境。
緩存的注釋寫法如下,加在Entity的java類上:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
四、Hibernate緩存的管理
一級緩存的管理:
evit(Object obj) 將指定的持久化對象從一級緩存中清除,釋放對象所占用的內(nèi)存資源,指定對象從持久化狀態(tài)變?yōu)槊摴軤顟B(tài),從而成為游離對象.
clear() 將一級緩存中的所有持久化對象清除,釋放其占用的內(nèi)存資源
contains(Object obj) 判斷指定的對象是否存在于一級緩存中.
flush() 刷新一級緩存區(qū)的內(nèi)容,使之與數(shù)據(jù)庫數(shù)據(jù)保持同步.
二級緩存的管理:
evict(Class arg0, Serializable arg1) 將某個類的指定ID的持久化對象從二級緩存中清除,釋放對象所占用的資源.
evictCollection(String arg0) 將指定類的所有持久化對象的指定集合從二級緩存中清除,釋放其占用的內(nèi)存資源.
如何避免一次性大量的實體數(shù)據(jù)入庫導致內(nèi)存溢出
*先flush,再clear
如果數(shù)據(jù)量特別大,考慮采用jdbc實現(xiàn),如果jdbc也不能滿足要求,可以考慮采用數(shù)據(jù)庫本身的特定導入工具
五、什么樣的數(shù)據(jù)不適合放在二級緩存中來?
下面這幾種情況就不適合加載到二級緩存中:
1.經(jīng)常被修改的數(shù)據(jù)
2.絕對不允許出現(xiàn)并發(fā)訪問的數(shù)據(jù)
3.與其他應用共享的數(shù)據(jù)
下面這己種情況合適加載到二級緩存中:
1.數(shù)據(jù)更新頻率低
2.允許偶爾出現(xiàn)并發(fā)問題的非重要數(shù)據(jù)
3.不會被并發(fā)訪問的數(shù)據(jù)
4.常量數(shù)據(jù)
5.不會被第三方修改的數(shù)據(jù)
六、二級緩存的配置
Hibernate的二級緩存功能是靠配置二級緩存插件來實現(xiàn)的,Hibernate為了集成這些插件,Hibernate提供了org.hibernate.cache.CacheProvider借口,它充當緩存插件與Hibernate之間的適配器 .
常用的二級緩存插件
EHCache org.hibernate.cache.EhCacheProvider
OSCache org.hibernate.cache.OSCacheProvider
SwarmCahe org.hibernate.cache.SwarmCacheProvider
JBossCache org.hibernate.cache.TreeCacheProvider
設(shè)置hibernate.cache.provider_class。
我們這里用ehcache,如
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
由于這是HIBERNATE默認的CACHE提供者, 所以無須做什么設(shè)置.
只要在src中添加ehcache的配置文件ehcache.xml:
- < ehcache>
- < diskStore path="java.io.tmpdir"/>
- < defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" />
- < cache name="goncha.hb.bean.Person" maxElementsInMemory="10" eternal="false"
- timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false" />
- < cache name="goncha.hb.bean.Address" maxElementsInMemory="10" eternal="false"
- timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false" />
- < /ehcache>
【編輯推薦】