詳解Hibernate中的二級快取
1.前言
這篇部落格再前幾篇部落格的基礎上來講解一下,Hibernate中的二級快取,二級快取是屬於SessionFactory級別的快取機制。第一級別的快取是Session級別的快取,是屬於事務範圍的快取,由Hibernate管理,一般無需進行干預。第二級別的快取是SessionFactory級別的快取,是屬於程序範圍的快取。
2.Hibernate二級快取
1.分類
二級快取也分為了兩種
內建快取:Hibernate自帶的,不可解除安裝,通常在Hibernate的初始化階段,Hibernate會把對映元資料和預定義的SQL語句放置到SessionFactory的快取中。該內建快取是隻讀的。
外接快取:通常說的二級快取也就是外接快取,在預設情況下SessionFactory不會啟用這個快取外掛,外接快取中的資料是資料庫資料的複製,外接快取的物理介質可以是記憶體或者硬碟。
hibernate二級快取的結構
2.併發訪問策略
transactional
(事務型)
僅在受管理的環境中適用
提供Repeatable Read事務隔離級別
適用經常被讀,很少修改的資料
可以防止髒讀和不可重複讀的併發問題
快取支援事務,發生異常的時候,快取也能夠回滾
read-write
(讀寫型)
提供Read Committed事務隔離級別
在非叢集的環境中適用
適用經常被讀,很少修改的資料
可以防止髒讀
更新快取的時候會鎖定快取中的資料
nonstrict-read-write
(非嚴格讀寫型)
適用極少被修改,偶爾允許髒讀的資料(兩個事務同時修改資料的情況很少見)
不保證快取和資料庫中資料的一致性
為快取資料設定很短的過期時間,從而儘量避免髒讀
不鎖定快取中的資料
read-only
(只讀型)
適用從來不會被修改的資料(如參考資料)
在此模式下,如果對資料進行更新操作,會有異常
事務隔離級別低,併發效能高
在叢集環境中也能完美運作
分析:通過上述表格分析如下
適合放入二級快取中資料
很少被修改
不是很重要的資料,允許出現偶爾的併發問題
不適合放入二級快取中的資料
經常被修改
財務資料,絕對不允許出現併發問題
與其他應用資料共享的資料
3.二級快取的配置
1.hibernate支援的快取外掛
•EHCache: 可作為程序範圍內的快取,存放資料的物理介質可以是記憶體或硬碟,對Hibernate的查詢快取提供了支援 •OpenSymphony`:可作為程序範圍內的快取,存放資料的物理介質可以是記憶體或硬碟,提供了豐富的快取資料過期策略,對Hibernate的查詢快取提供了支援 •SwarmCache:可作為叢集範圍內的快取,但不支援Hibernate的查詢快取 •JBossCache:可作為叢集範圍內的快取,支援Hibernate的查詢快取 四種快取外掛支援的併發範圍策略如下圖
2.二級快取配置
下面以ehcache快取為例,來講一下二級快取的配置
2.1 拷貝jar包
如要第三方的jar包ehcache-1.5.0.jar,並且依賴於
依賴backport-util-concurrent 和 commons-logging
2.2 在hibernate.cfg.xml中開啟二級快取
<propertyname="hibernate.cache.use_second_level_cache">true</property>
2.3 配置二級快取技術提供商
<propertyname="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
2.4 配置快取資料物件併發策略
方式一 在hbm檔案中配置
<span style="font-family:SimSun;font-size:18px;"><class name="cn.itcast.domain.Customer" table="customers" catalog="hibernate3day4" > <!-- 類級別快取 --> <cache usage="read-write"/> <set name="orders" cascade="all-delete-orphan" inverse="true" > <!-- 關聯集合級別快取 --> <cache usage="read-write"/> </set> </class> </span>
方式二 在cfg檔案配置(集中配置)
<span style="font-family:SimSun;font-size:18px;"><!-- 類級別快取 --> <class-cache usage="read-write" class="cn.itcast.domain.Customer"/> <class-cache usage="read-write" class="cn.itcast.domain.Order"/> <!-- 集合快取 --> <collection-cache usage="read-write" collection="cn.itcast.domain.Customer.orders"/> </span>
2.5 新增二級快取配置檔案
在src中配置ehcache.xml,將ehcache.jar包中的ehcache-failsafe.xml 改名 ehcache.xml 放入 src
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="java.io.tmpdir"/> 配置二級快取硬碟臨時目錄位置 <defaultCache maxElementsInMemory="10000" // 記憶體中最大物件數量 ,超過數量,資料會被快取到硬碟 eternal="false" timeToIdleSeconds="120" // 是否快取為永久性 false 不永久 timeToLiveSeconds="120" // 存活時間,物件不管是否使用,到了時間回收 overflowToDisk="true" // 是否可以快取到硬碟 maxElementsOnDisk="10000000" // 硬碟快取最大物件數量 // 當jvm結束時是否持久化物件 true false 預設是false diskExpiryThreadIntervalSeconds="120" // 指定專門用於清除過期物件的監聽執行緒的輪詢時間 memoryStoreEvictionPolicy="LRU" /> </ehcache>
4.Demo測試二級快取
@Test public void fun1() { Session s1 = HibernateUtils.getSession(); s1.beginTransaction(); Customer c1 = (Customer) s1.get(Customer.class, 1); // 從資料庫中載入資料 System.out.println(c1.getName());//此時才會發出SQL語句 s1.getTransaction().commit(); s1.close(); // 關閉session級別的一級快取 Session s2 = HibernateUtils.getSession(); s2.beginTransaction(); Customer c2 = (Customer) s2.get(Customer.class, 1); // 因為有了二級快取的存在,直接從二級快取中取出即可 System.out.println(c2.getName()); Customer c3 = (Customer) s2.get(Customer.class, 1); //從二級快取中取出 System.out.println(c3.getName()); s2.getTransaction().commit(); s2.close(); }