1. 程式人生 > >詳解Hibernate中的二級快取

詳解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();

	}