Hibernate的緩存機制


一、緩存的范圍分為3類: 
    1、事務范圍(單Session即一級緩存) 
   事務范圍的緩存只能被當前事務訪問,每個事務都有各自的緩存,緩存內的數據通常采用相互關聯的對象形式.緩存的生命周期依賴於事務的生命周期,只有當事務結束時,緩存的生命周期才會結束.事務范圍的緩存使用內存作為存儲介質,一級緩存就屬於事務范圍. 
 
    2、應用范圍(單SessionFactory即二級緩存) 
      應用程序的緩存可以被應用范圍內的所有事務共享訪問.緩存的生命周期依賴於應用的生命周期,只有當應用結束時,緩存的生命周期才會結束.應用范圍的緩存可以使用內存或硬盤作為存儲介質,二級緩存就屬於應用范圍. 
 
    3、集群范圍(多SessionFactory) 
   在集群環境中,緩存被一個機器或多個機器的進程共享,緩存中的數據被復制到集群環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致,緩存中的數據通常采用對象的松散數據形式.
 
二、一級緩存:
  1、使用一級緩存的目的是為了減少對數據庫的訪問次數,從而提升hibernate的執行效率;(當執行一次查詢操作的時候,執行第二次查詢操作,先檢查緩存中是否有數據,如果有數據就不查詢數據庫,直接從緩存中獲取數據);
   2、Hibernate中的一級緩存,也叫做session的緩存,它可以在session范圍內減少數據庫的訪問次數,只在session范圍內有效,session關閉,一級緩存失敗;
  3、一級緩存的特點,只在session范圍有效,作用時間短,效果不是特別明顯,在短時間內多次操作數據庫,效果比較明顯。
  4、當調用session的save/saveOrUpdate/get/load/list/iterator方法的時候,都會把對象放入session緩存中;
  5、session的緩存是由hibernate維護的,用戶不能操作緩存內容;如果想操作緩存內容,必須通過hibernate提供的evict/clear方法操作
  6、緩存相關的方法(在什么情況下使用上面方法呢?批量操作情況下使用,如Session.flush();先與數據庫同步,Session.clear();再清空一級緩存內容):
    session.flush();讓一級緩存與數據庫同步;
    session.evict();清空一級緩存中指定的對象;
    session.clear();清空一級緩存中所有的對象;
 
二、二級緩存 : 基於應用程序級別的緩存,作用在SessionFactory范圍內的, 可以跨多個session,即不同的session都可以訪問緩存。 Hibernate提供的二級緩存有默認的實現,且是一種可插配的緩存框架!如果用戶想用二級緩存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影響代碼。
 
    1、在執行各種條件查詢時,如果所獲得的結果集為實體對象的集合,那么就會把所有的數據對象根據ID放入到二級緩存中。
 
     2、當Hibernate根據ID訪問數據對象的時候,首先會從Session一級緩存中查找,如果查不到並且配置了二級緩存,那么會從二級緩存中查找,如果還查不到,就會查詢數據庫,把結果按照ID放入到緩存中。 
 
     3、刪除、更新、增加數據的時候,同時更新緩存。
 
注意:
  在通常情況下會將具有以下特征的數據放入到二級緩存中: 
     ● 很少被修改的數據。 
     ● 不是很重要的數據,允許出現偶爾並發的數據。 
     ● 不會被並發訪問的數據。 
     ● 常量數據。 
     ● 不會被第三方修改的數據 
 
  而對於具有以下特征的數據則不適合放在二級緩存中: 
    ● 經常被修改的數據。 
    ● 財務數據,絕對不允許出現並發。 
    ● 與其他應用共享的數據。 
 
三、二級緩存配置步驟: 在默認情況下,Hibernate會使用EHCache作為二級緩存組件。但是,可以通過設置hibernate.cache.provider_class屬性,指定其他的緩存策略,該緩存策略必須實現org.hibernate.cache.CacheProvider接口。 通過實現org.hibernate.cache.CacheProvider接口可以提供對不同二級緩存組件的支持,此接口充當緩存插件與Hibernate之間的適配器。
組件
Provider類
類型
集群
查詢緩存
Hashtable
org.hibernate.cache.HashtableCacheProvider
內存
不支持
支持
EHCache
org.hibernate.cache.EhCacheProvider
內存,硬盤
不支持
支持
OSCache
org.hibernate.cache.OSCacheProvider
內存,硬盤
支持
支持
SwarmCache
org.hibernate.cache.SwarmCacheProvider
集群
支持
不支持
JBoss TreeCache
org.hibernate.cache.TreeCacheProvider
集群
支持
支持
1.添加jar包,如ehcache-core.jar
2.在hibernate.cfg.xml開啟二級緩存Xml代碼
 
<!-- a. 開啟二級緩存 -->
  <property name="hibernate.cache.use_second_level_cache">true</property>
<!-- b. 指定使用哪一個緩存框架(默認提供的) -->
  <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 開啟查詢緩存 -->
  <property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些類,需要加入二級緩存 -->
  <class-cache usage="read-write" class="com.bie.lesson11.Dept"/>
  <class-cache usage="read-only" class="com.bie.lesson11.Employee"/>
<!-- 集合緩存[集合緩存的元素對象,也加加入二級緩存] -->
  <collection-cache usage="read-write" collection="com.bie.lesson11.Dept.emps"/>
 
3.ehcache.xml配置(可選)
cache參數詳解: 
● name:指定區域名 
● maxElementsInMemory :緩存在內存中的最大數目 
● maxElementsOnDisk:緩存在磁盤上的最大數目 
● eternal :設置是否永遠不過期 
● overflowToDisk : 硬盤溢出數目 
● timeToIdleSeconds :對象處於空閑狀態的最多秒數后銷毀 
● timeToLiveSeconds :對象處於緩存狀態的最多秒數后銷毀 
● memoryStoreEvictionPolicy:緩存算法,有LRU(默認)、LFU、LFU 
 
關於緩存算法,常見有三種: 
● LRU:(Least Rencently Used)新來的對象替換掉使用時間算最近很少使用的對象 
● LFU:(Least Frequently Used)替換掉按命中率高低算比較低的對象 
● LFU:(First In First Out)把最早進入二級緩存的對象替換掉 
 
<?xml version="1.0" encoding="UTF-8"?>  
<ehcache>  
  <!--如果緩存中的對象存儲超過指定的緩存數量的對象存儲的磁盤地址-->  
  <diskStore path="D:/ehcache"/>  
  
  <!-- 默認cache:如果沒有對應的特定區域的緩存,就使用默認緩存 -->  
  <defaultCache maxElementsInMemory="10000"  
                eternal="false"  
                timeToIdleSeconds="300"   
                timeToLiveSeconds="600"  
                overflowToDisk="false"/>  
  <!-- 指定區域cache:通過name指定,name對應到Hibernate中的區域名即可-->  
  <cache name="cn.javass.h3test.model.UserModel"  
                eternal="false"  
                maxElementsInMemory="100"  
                timeToIdleSeconds="1200"  
                timeToLiveSeconds="1200"  
                overflowToDisk="false">  
  </cache>  
</ehcache>  
 
4.實體類的映射文件配置,如user.hbm.xml的配置
<?xml version="1.0" encoding='UTF-8'?>  
<!DOCTYPE hibernate-mapping PUBLIC  
                            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
                            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd>  
<hibernate-mapping>      
   <class>  
       <!-- 設置該持久化類的二級緩存並發訪問策略 read-only read-write nonstrict-read-write transactional-->  
       <class name="cn.java.test.model.User" table="TBL_USER">  
              <cache usage="read-write"/>  
       ......    
   </class>  
</hibernate-mapping> 
 
(1)其中二級緩存並發訪問策略有三種:
   a.在user.hbm.xml中添加<cache usage="read-write"/> 
   b.在hibernate.cfg.xml中添加<class-cache usage="read-write" class="com.hb.test.User"/>
   c.用Hibernate注解配置緩存實體類 
 
(2) 二級緩存策略 
  ● READ_ONLY:實體只讀緩存 
   只讀緩存不允許更新,將報錯Can't write to a readonly object。 
   允許新增,(從2.0以后新增直接添加到二級緩存) 
 
//確保數據庫中有標識符為1的FarmModel    
FarmModel farm = (FarmModel) session.get(FarmModel.class1);    
//如果修改將報錯,只讀緩存不允許修改    
//farm.setName("aaa");  
 
  ● NONSTRICT_READ_WRITE:實體非嚴格讀/寫緩存 
     允許更新,更新后緩存失效,需再查詢一次。 
     允許新增,新增記錄自動加到二級緩存中。 
     整個過程不加鎖。 
  ● READ_WRITE:實體讀/寫緩存 
     允許更新,更新后自動同步到緩存。 
     允許新增,新增記錄后自動同步到緩存。 
     保證read committed隔離級別及可重復讀隔離級別(通過時間戳實現) 
     整個過程加鎖,如果當前事務的時間戳早於二級緩存中的條目的時間戳,說明該條目已經被別的 
     事務修改了,此時重新查詢一次數據庫,否則才使用緩存數據,因此保證可重復讀隔離級別。 
     讀寫緩存和不嚴格讀寫緩存在實現上的區別在於,讀寫緩存更新緩存的時候會把緩存里面的數據換成一個鎖 
  ● TRANSACTIONAL:實體事務緩存 
      緩存支持事務,發生異常的時候,緩存也能夠回滾,只支持jta環境 
  ● Collection集合緩存 
 
<hibernate-mapping>  
    <class name="cn.java.test.model.UserModel" table="TBL_USER">  
        <cache usage="read-write" />  
        <set name="farms" cascade="all" inverse="true" lazy="false">  
            <cache usage="read-write"/>  
            <key column="fk_user_id"/>  
            <one-to-many class="cn.java.test.model.FarmModel"/>  
        </set>  
    </class>  
</hibernate-mapping>  
 


免責聲明!

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



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