Cache簡介: 緩存(Cache )是計算機領(lǐng)域非常通用的概念。它介于應(yīng)用程序和永久性數(shù)據(jù)存儲源(如硬盤上的文件或者數(shù)據(jù)庫)之間,其作用是降低應(yīng)用程序直接讀寫永久性數(shù)據(jù)存儲源的頻率,從而提高應(yīng)用的運行性能。緩存中的數(shù)據(jù)是數(shù)據(jù)存儲源中數(shù)據(jù)的拷貝,應(yīng)用程序在運行時直接讀寫緩存中的數(shù)據(jù),只在某些特定時刻按照緩存中的數(shù)據(jù)來同步更新數(shù)據(jù)存儲源。
緩存的物理介質(zhì)通常是內(nèi)存,而永久性數(shù)據(jù)存儲源的物理介質(zhì)通常是硬盤或磁盤,應(yīng)用程序讀寫內(nèi)在的速度顯然比讀寫硬盤的速度快,如果緩存中存放的數(shù)據(jù)量非常大,也會用硬盤作為緩存的物理介質(zhì)。
緩存的實現(xiàn)不僅需要作為物理介質(zhì)的硬件,同時還需要用于管理緩存的并發(fā)訪問和過期等策略的軟件。因此,緩存是通過軟件和硬件共同實現(xiàn)的。
1.1. 持久化層的緩存的范圍
緩存的范圍決定了緩存的生命周期以及可以被誰訪問。緩存的范圍分為三類。
1) 事務(wù)范圍:緩存只能被當(dāng)前事務(wù)訪問。緩存的生命周期依賴于事務(wù)的生命周期,當(dāng)事務(wù)結(jié)束時,緩存也就結(jié)束生命周期。在此范圍下,緩存的介質(zhì)是內(nèi)存。事務(wù)可以是數(shù)據(jù)庫事務(wù)或者應(yīng)用事務(wù),每個事務(wù)都有獨自的緩存,緩存內(nèi)的數(shù)據(jù)通常采用相互關(guān)聯(lián)的對象形式。
2) 進(jìn)程范圍:緩存被進(jìn)程內(nèi)的所有事務(wù)共享。這些事務(wù)有可能是并發(fā)訪問緩存,因此必須對緩存采取必要的事務(wù)隔離機制。緩存的生命周期依賴于進(jìn)程的生命周期,進(jìn)程結(jié)束時,緩存也就結(jié)束了生命周期。進(jìn)程范圍的緩存可能會存放大量的數(shù)據(jù),所以存放的介質(zhì)可以是內(nèi)存或硬盤。緩存內(nèi)的數(shù)據(jù)既可以是相互關(guān)聯(lián)的對象形式也可以是對象的松散數(shù)據(jù)形式。松散的對象數(shù)據(jù)形式有點類似于對象的序列化數(shù)據(jù),但是對象分解為松散的算法比對象序列化的算法要求更快。
3) 集群范圍:在集群環(huán)境中,緩存被一個機器或者多個機器的進(jìn)程共享。緩存中的數(shù)據(jù)被復(fù)制到集群環(huán)境中的每個進(jìn)程節(jié)點,進(jìn)程間通過遠(yuǎn)程通信來保證緩存中的數(shù)據(jù)的一致性,緩存中的數(shù)據(jù)通常采用對象的松散數(shù)據(jù)形式。
對大多數(shù)應(yīng)用來說,應(yīng)該慎重地考慮是否需要使用集群范圍的緩存,因為訪問的速度不一定會比直接訪問數(shù)據(jù)庫數(shù)據(jù)的速度快多少。
持久化層可以提供多種范圍的緩存。如果在事務(wù)范圍的緩存中沒有查到相應(yīng)的數(shù)據(jù),還可以到進(jìn)程范圍或集群范圍的緩存內(nèi)查詢,如果還是沒有查到,那么只有到數(shù)據(jù)庫中查詢。事務(wù)范圍的緩存是持久化層的第一級緩存,通常它是必需的;進(jìn)程范圍或集群范圍的緩存是持久化層的第二級緩存,通常是可選的。
1.2. 持久化層的緩存的并發(fā)訪問策略
當(dāng)多個并發(fā)的事務(wù)同時訪問持久化層的緩存的相同數(shù)據(jù)時,會引起并發(fā)問題,必須采用必要的事務(wù)隔離措施。
在進(jìn)程范圍或集群范圍的緩存,即第二級緩存,會出現(xiàn)并發(fā)問題。因此可以設(shè)定以下四種類型的并發(fā)訪問策略,每一種策略對應(yīng)一種事務(wù)隔離級別。
1) 事務(wù)型(Transactional)策略:僅僅在受管理環(huán)境中適用。它提供了Repeatable Read事務(wù)隔離級別。對于經(jīng)常被讀但很少修改的數(shù)據(jù),可以采用這種隔離類型,因為它可以防止臟讀和不可重復(fù)讀這類的并發(fā)問題。
2) 讀寫型(read-write)策略:提供了Read Committed事務(wù)隔離級別。僅僅在非集群的環(huán)境中適用。對于經(jīng)常被讀但很少修改的數(shù)據(jù),可以采用這種隔離類型,因為它可以防止臟讀這類的并發(fā)問題。
3) 非嚴(yán)格讀寫型(nonstrict-read-write)策略:不保證緩存與數(shù)據(jù)庫中數(shù)據(jù)的一致性。如果存在兩個事務(wù)同時訪問緩存中相同數(shù)據(jù)的可能,必須為該數(shù)據(jù)配置一個很短的數(shù)據(jù)過期時間,從而盡量避免臟讀。對于極少被修改,并且允許偶爾臟讀的數(shù)據(jù),可以采用這種并發(fā)訪問策略。
4) 只讀型策略(read-only):對于從來不會修改的數(shù)據(jù),如參考數(shù)據(jù),可以使用這種并發(fā)訪問策略。
事務(wù)型并發(fā)訪問策略是事務(wù)隔離級別最高,只讀型的隔離級別最低。事務(wù)隔離級別越高,并發(fā)性能就越低。
2. Hibernate中的緩存:
Hibernate中提供了兩級Cache,第一級別的緩存是Session級別的緩存,它是屬于事務(wù)范圍的緩存。這一級別的緩存由hibernate管理的,一般情況下無需進(jìn)行干預(yù);第二級別的緩存是SessionFactory級別的緩存,它是屬于進(jìn)程范圍或群集范圍的緩存。這一級別的緩存可以進(jìn)行配置和更改,并且可以動態(tài)加載和卸載。
Hibernate還為查詢結(jié)果提供了一個查詢緩存,它依賴于第二級緩存。
2.1. 一級緩存和二級緩存的比較:
第一級緩存
第二級緩存
存放數(shù)據(jù)的形式
相互關(guān)聯(lián)的持久化對象
對象的散裝數(shù)據(jù)
緩存的范圍
事務(wù)范圍,每個事務(wù)都有單獨的第一級緩存
進(jìn)程范圍或集群范圍,緩存被同一個進(jìn)程或集群范圍內(nèi)的所有事務(wù)共享
并發(fā)訪問策略
由于每個事務(wù)都擁有單獨的第一級緩存,不會出現(xiàn)并發(fā)問題,無需提供并發(fā)訪問策略
由于多個事務(wù)會同時訪問第二級緩存中相同數(shù)據(jù),因此必須提供適當(dāng)?shù)牟l(fā)訪問策略,來保證特定的事務(wù)隔離級別
數(shù)據(jù)過期策略
沒有提供數(shù)據(jù)過期策略。處于一級緩存中的對象永遠(yuǎn)不會過期,除非應(yīng)用程序顯式清空緩存或者清除特定的對象
必須提供數(shù)據(jù)過期策略,如基于內(nèi)存的緩存中的對象的最大數(shù)目,允許對象處于緩存中的最長時間,以及允許對象處于緩存中的最長空閑時間
物理存儲介質(zhì)
內(nèi)存
內(nèi)存和硬盤。對象的散裝數(shù)據(jù)首先存放在基于內(nèi)在的緩存中,當(dāng)內(nèi)存中對象的數(shù)目達(dá)到數(shù)據(jù)過期策略中指定上限時,就會把其余的對象寫入基于硬盤的緩存中。
緩存的軟件實現(xiàn)
在Hibernate的Session的實現(xiàn)中包含了緩存的實現(xiàn)
由第三方提供,Hibernate僅提供了緩存適配器(CacheProvider)。用于把特定的緩存插件集成到Hibernate中。
啟用緩存的方式
只要應(yīng)用程序通過Session接口來執(zhí)行保存、更新、刪除、加載和查詢數(shù)據(jù)庫數(shù)據(jù)的操作,Hibernate就會啟用第一級緩存,把數(shù)據(jù)庫中的數(shù)據(jù)以對象的形式拷貝到緩存中,對于批量更新和批量刪除操作,如果不希望啟用第一級緩存,可以繞過Hibernate API,直接通過JDBC API來執(zhí)行指操作。
用戶可以在單個類或類的單個集合的粒度上配置第二級緩存。如果類的實例被經(jīng)常讀但很少被修改,就可以考慮使用第二級緩存。只有為某個類或集合配置了第二級緩存,Hibernate在運行時才會把它的實例加入到第二級緩存中。
用戶管理緩存的方式
第一級緩存的物理介質(zhì)為內(nèi)存,由于內(nèi)存容量有限,必須通過恰當(dāng)?shù)臋z索策略和檢索方式來限制加載對象的數(shù)目。Session的evit()方法可以顯式清空緩存中特定對象,但這種方法不值得推薦。
第二級緩存的物理介質(zhì)可以是內(nèi)存和硬盤,因此第二級緩存可以存放大量的數(shù)據(jù),數(shù)據(jù)過期策略的maxElementsInMemory屬性值可以控制內(nèi)存中的對象數(shù)目。管理第二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久類,設(shè)置合適的并發(fā)訪問策略:選擇緩存適配器,設(shè)置合適的數(shù)據(jù)過期策略。
2.2. 一級緩存的管理:
當(dāng)應(yīng)用程序調(diào)用Session的save()、update()、savaeOrUpdate()、get()或load(),以及調(diào)用查詢接口的list()、iterate()或filter()方法時,如果在Session緩存中還不存在相應(yīng)的對象,Hibernate就會把該對象加入到第一級緩存中。當(dāng)清理緩存時,Hibernate會根據(jù)緩存中對象的狀態(tài)變化來同步更新數(shù)據(jù)庫。
Session為應(yīng)用程序提供了兩個管理緩存的方法:
evict(Object obj):從緩存中清除參數(shù)指定的持久化對象。
clear():清空緩存中所有持久化對象。
2.3. 二級緩存的管理:
2.3.1. Hibernate 的二級緩存策略的一般過程如下:
1) 條件查詢的時候,總是發(fā)出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數(shù)據(jù)庫,一次獲得所有的數(shù)據(jù)對象。
2) 把獲得的所有數(shù)據(jù)對象根據(jù)ID放入到第二級緩存中。
3) 當(dāng)Hibernate根據(jù)ID訪問數(shù)據(jù)對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數(shù)據(jù)庫,把結(jié)果按照ID放入到緩存。
4) 刪除、更新、增加數(shù)據(jù)的時候,同時更新緩存。
Hibernate的二級緩存策略,是針對于ID查詢的緩存策略,對于條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query Cache。
2.3.2. 什么樣的數(shù)據(jù)適合存放到第二級緩存中?
1 很少被修改的數(shù)據(jù)
2 不是很重要的數(shù)據(jù),允許出現(xiàn)偶爾并發(fā)的數(shù)據(jù)
3 不會被并發(fā)訪問的數(shù)據(jù)
4 參考數(shù)據(jù),指的是供應(yīng)用參考的常量數(shù)據(jù),它的實例數(shù)目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。
2.3.3. 不適合存放到第二級緩存的數(shù)據(jù)?
1 經(jīng)常被修改的數(shù)據(jù)
2 財務(wù)數(shù)據(jù),絕對不允許出現(xiàn)并發(fā)
3 與其他應(yīng)用共享的數(shù)據(jù)。
2.3.4. 常用的緩存插件
Hibernater 的二級緩存是一個插件,下面是幾種常用的緩存插件:
l EhCache:可作為進(jìn)程范圍的緩存,存放數(shù)據(jù)的物理介質(zhì)可以是內(nèi)存或硬盤,對Hibernate的查詢緩存提供了支持。
l OSCache:可作為進(jìn)程范圍的緩存,存放數(shù)據(jù)的物理介質(zhì)可以是內(nèi)存或硬盤,提供了豐富的緩存數(shù)據(jù)過期策略,對Hibernate的查詢緩存提供了支持。
l SwarmCache:可作為群集范圍內(nèi)的緩存,但不支持Hibernate的查詢緩存。
l JBossCache:可作為群集范圍內(nèi)的緩存,支持事務(wù)型并發(fā)訪問策略,對Hibernate的查詢緩存提供了支持。
2.3.5. 配置二級緩存的主要步驟:
1) 選擇需要使用二級緩存的持久化類,設(shè)置它的命名緩存的并發(fā)訪問策略。這是最值得認(rèn)真考慮的步驟。
2) 選擇合適的緩存插件,然后編輯該插件的配置文件。
1. 首先設(shè)置EhCache,建立配置文件ehcache.xml,默認(rèn)的位置在class-path,可以放到你的src目錄下:
<ehcache>
<diskStore path="c:\\ehcache\"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 設(shè)置Category類的緩存的數(shù)據(jù)過期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- 設(shè)置Category類的products集合的緩存的數(shù)據(jù)過期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category.products"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="org.qiujy.domain.cachedemo.Product"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
配置的元素說明:
元素或?qū)傩?/strong>
描述
<diskStore>
設(shè)置緩存數(shù)據(jù)文件的存放目錄
<defaultCache>
設(shè)置緩存的默認(rèn)數(shù)據(jù)過期策略
<cache>
設(shè)定具體的命名緩存的數(shù)據(jù)過期策略
每個命名緩存代表一個緩存區(qū)域,每個緩存區(qū)域有各自的數(shù)據(jù)過期策略。命名緩存機制使得用戶能夠在每個類以及類的每
2. 在Hibernate配置文件中設(shè)置:
<hibernate-configuration>
<session-factory>……<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><property name="cache.use_second_level_cache">true</property>……</session-factory></hibernate-configuration> 此外,可以把cache.use_second_level_cache設(shè)置為false關(guān)閉所有的hibernate二級緩存。但此屬性對指定<cache>的類缺省為true。
3. 為了使用二級緩存,需要在每一個Hibernate Entity上配置。
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Forest { ... }
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public SortedSet getTickets() {
return tickets;
}
@Cache(
CacheConcurrencyStrategy usage(); (1)
String region()default ""; (2)
String include()default "all"; (3)
)
(1) usage: 提供緩存對象的事務(wù)隔離機制,可選值有以下幾種
(NONE, READ_ONLY, NONSTRICT_READ_WRITE(非嚴(yán)格讀寫), READ_WRITE, TRANSACTIONAL)
(2) region (optional): 指定緩存的區(qū)域,默認(rèn)是類的全限定名。利用緩存區(qū)域,可以更精確的指定每個區(qū)域的緩存超前策略。如果指定了緩存區(qū)域前綴(在hibernate.cfg.xml中設(shè)置cache.region_prefix屬性為一個字符串),則所有的緩存區(qū)域名前將加上這個前綴。
(3) include (optional): all to include all properties, non-lazy to only include non lazy properties (default all).
如果不是使用annotation的話,則是在Hbm文件中添加cache usage="read-only"
http://blog.163.com/seara520@126/blog/static/7206930420102232340810/
緩存的物理介質(zhì)通常是內(nèi)存,而永久性數(shù)據(jù)存儲源的物理介質(zhì)通常是硬盤或磁盤,應(yīng)用程序讀寫內(nèi)在的速度顯然比讀寫硬盤的速度快,如果緩存中存放的數(shù)據(jù)量非常大,也會用硬盤作為緩存的物理介質(zhì)。
緩存的實現(xiàn)不僅需要作為物理介質(zhì)的硬件,同時還需要用于管理緩存的并發(fā)訪問和過期等策略的軟件。因此,緩存是通過軟件和硬件共同實現(xiàn)的。
緩存的范圍決定了緩存的生命周期以及可以被誰訪問。緩存的范圍分為三類。
1) 事務(wù)范圍:緩存只能被當(dāng)前事務(wù)訪問。緩存的生命周期依賴于事務(wù)的生命周期,當(dāng)事務(wù)結(jié)束時,緩存也就結(jié)束生命周期。在此范圍下,緩存的介質(zhì)是內(nèi)存。事務(wù)可以是數(shù)據(jù)庫事務(wù)或者應(yīng)用事務(wù),每個事務(wù)都有獨自的緩存,緩存內(nèi)的數(shù)據(jù)通常采用相互關(guān)聯(lián)的對象形式。
2) 進(jìn)程范圍:緩存被進(jìn)程內(nèi)的所有事務(wù)共享。這些事務(wù)有可能是并發(fā)訪問緩存,因此必須對緩存采取必要的事務(wù)隔離機制。緩存的生命周期依賴于進(jìn)程的生命周期,進(jìn)程結(jié)束時,緩存也就結(jié)束了生命周期。進(jìn)程范圍的緩存可能會存放大量的數(shù)據(jù),所以存放的介質(zhì)可以是內(nèi)存或硬盤。緩存內(nèi)的數(shù)據(jù)既可以是相互關(guān)聯(lián)的對象形式也可以是對象的松散數(shù)據(jù)形式。松散的對象數(shù)據(jù)形式有點類似于對象的序列化數(shù)據(jù),但是對象分解為松散的算法比對象序列化的算法要求更快。
3) 集群范圍:在集群環(huán)境中,緩存被一個機器或者多個機器的進(jìn)程共享。緩存中的數(shù)據(jù)被復(fù)制到集群環(huán)境中的每個進(jìn)程節(jié)點,進(jìn)程間通過遠(yuǎn)程通信來保證緩存中的數(shù)據(jù)的一致性,緩存中的數(shù)據(jù)通常采用對象的松散數(shù)據(jù)形式。
對大多數(shù)應(yīng)用來說,應(yīng)該慎重地考慮是否需要使用集群范圍的緩存,因為訪問的速度不一定會比直接訪問數(shù)據(jù)庫數(shù)據(jù)的速度快多少。
當(dāng)多個并發(fā)的事務(wù)同時訪問持久化層的緩存的相同數(shù)據(jù)時,會引起并發(fā)問題,必須采用必要的事務(wù)隔離措施。
在進(jìn)程范圍或集群范圍的緩存,即第二級緩存,會出現(xiàn)并發(fā)問題。因此可以設(shè)定以下四種類型的并發(fā)訪問策略,每一種策略對應(yīng)一種事務(wù)隔離級別。
1) 事務(wù)型(Transactional)策略:僅僅在受管理環(huán)境中適用。它提供了Repeatable Read事務(wù)隔離級別。對于經(jīng)常被讀但很少修改的數(shù)據(jù),可以采用這種隔離類型,因為它可以防止臟讀和不可重復(fù)讀這類的并發(fā)問題。
2) 讀寫型(read-write)策略:提供了Read Committed事務(wù)隔離級別。僅僅在非集群的環(huán)境中適用。對于經(jīng)常被讀但很少修改的數(shù)據(jù),可以采用這種隔離類型,因為它可以防止臟讀這類的并發(fā)問題。
3) 非嚴(yán)格讀寫型(nonstrict-read-write)策略:不保證緩存與數(shù)據(jù)庫中數(shù)據(jù)的一致性。如果存在兩個事務(wù)同時訪問緩存中相同數(shù)據(jù)的可能,必須為該數(shù)據(jù)配置一個很短的數(shù)據(jù)過期時間,從而盡量避免臟讀。對于極少被修改,并且允許偶爾臟讀的數(shù)據(jù),可以采用這種并發(fā)訪問策略。
4) 只讀型策略(read-only):對于從來不會修改的數(shù)據(jù),如參考數(shù)據(jù),可以使用這種并發(fā)訪問策略。
事務(wù)型并發(fā)訪問策略是事務(wù)隔離級別最高,只讀型的隔離級別最低。事務(wù)隔離級別越高,并發(fā)性能就越低。
Hibernate中提供了兩級Cache,第一級別的緩存是Session級別的緩存,它是屬于事務(wù)范圍的緩存。這一級別的緩存由hibernate管理的,一般情況下無需進(jìn)行干預(yù);第二級別的緩存是SessionFactory級別的緩存,它是屬于進(jìn)程范圍或群集范圍的緩存。這一級別的緩存可以進(jìn)行配置和更改,并且可以動態(tài)加載和卸載。
Hibernate還為查詢結(jié)果提供了一個查詢緩存,它依賴于第二級緩存。
相互關(guān)聯(lián)的持久化對象
對象的散裝數(shù)據(jù)
事務(wù)范圍,每個事務(wù)都有單獨的第一級緩存
進(jìn)程范圍或集群范圍,緩存被同一個進(jìn)程或集群范圍內(nèi)的所有事務(wù)共享
由于每個事務(wù)都擁有單獨的第一級緩存,不會出現(xiàn)并發(fā)問題,無需提供并發(fā)訪問策略
由于多個事務(wù)會同時訪問第二級緩存中相同數(shù)據(jù),因此必須提供適當(dāng)?shù)牟l(fā)訪問策略,來保證特定的事務(wù)隔離級別
沒有提供數(shù)據(jù)過期策略。處于一級緩存中的對象永遠(yuǎn)不會過期,除非應(yīng)用程序顯式清空緩存或者清除特定的對象
必須提供數(shù)據(jù)過期策略,如基于內(nèi)存的緩存中的對象的最大數(shù)目,允許對象處于緩存中的最長時間,以及允許對象處于緩存中的最長空閑時間
內(nèi)存
內(nèi)存和硬盤。對象的散裝數(shù)據(jù)首先存放在基于內(nèi)在的緩存中,當(dāng)內(nèi)存中對象的數(shù)目達(dá)到數(shù)據(jù)過期策略中指定上限時,就會把其余的對象寫入基于硬盤的緩存中。
在Hibernate的Session的實現(xiàn)中包含了緩存的實現(xiàn)
由第三方提供,Hibernate僅提供了緩存適配器(CacheProvider)。用于把特定的緩存插件集成到Hibernate中。
只要應(yīng)用程序通過Session接口來執(zhí)行保存、更新、刪除、加載和查詢數(shù)據(jù)庫數(shù)據(jù)的操作,Hibernate就會啟用第一級緩存,把數(shù)據(jù)庫中的數(shù)據(jù)以對象的形式拷貝到緩存中,對于批量更新和批量刪除操作,如果不希望啟用第一級緩存,可以繞過Hibernate API,直接通過JDBC API來執(zhí)行指操作。
用戶可以在單個類或類的單個集合的粒度上配置第二級緩存。如果類的實例被經(jīng)常讀但很少被修改,就可以考慮使用第二級緩存。只有為某個類或集合配置了第二級緩存,Hibernate在運行時才會把它的實例加入到第二級緩存中。
第一級緩存的物理介質(zhì)為內(nèi)存,由于內(nèi)存容量有限,必須通過恰當(dāng)?shù)臋z索策略和檢索方式來限制加載對象的數(shù)目。Session的evit()方法可以顯式清空緩存中特定對象,但這種方法不值得推薦。
第二級緩存的物理介質(zhì)可以是內(nèi)存和硬盤,因此第二級緩存可以存放大量的數(shù)據(jù),數(shù)據(jù)過期策略的maxElementsInMemory屬性值可以控制內(nèi)存中的對象數(shù)目。管理第二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久類,設(shè)置合適的并發(fā)訪問策略:選擇緩存適配器,設(shè)置合適的數(shù)據(jù)過期策略。
當(dāng)應(yīng)用程序調(diào)用Session的save()、update()、savaeOrUpdate()、get()或load(),以及調(diào)用查詢接口的list()、iterate()或filter()方法時,如果在Session緩存中還不存在相應(yīng)的對象,Hibernate就會把該對象加入到第一級緩存中。當(dāng)清理緩存時,Hibernate會根據(jù)緩存中對象的狀態(tài)變化來同步更新數(shù)據(jù)庫。
Session為應(yīng)用程序提供了兩個管理緩存的方法:
evict(Object obj):從緩存中清除參數(shù)指定的持久化對象。
clear():清空緩存中所有持久化對象。
1) 條件查詢的時候,總是發(fā)出一條select * from table_name where …. (選擇所有字段)這樣的SQL語句查詢數(shù)據(jù)庫,一次獲得所有的數(shù)據(jù)對象。
2) 把獲得的所有數(shù)據(jù)對象根據(jù)ID放入到第二級緩存中。
3) 當(dāng)Hibernate根據(jù)ID訪問數(shù)據(jù)對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那么從二級緩存中查;查不到,再查詢數(shù)據(jù)庫,把結(jié)果按照ID放入到緩存。
4) 刪除、更新、增加數(shù)據(jù)的時候,同時更新緩存。
Hibernate的二級緩存策略,是針對于ID查詢的緩存策略,對于條件查詢則毫無作用。為此,Hibernate提供了針對條件查詢的Query Cache。
1 很少被修改的數(shù)據(jù)
2 不是很重要的數(shù)據(jù),允許出現(xiàn)偶爾并發(fā)的數(shù)據(jù)
3 不會被并發(fā)訪問的數(shù)據(jù)
4 參考數(shù)據(jù),指的是供應(yīng)用參考的常量數(shù)據(jù),它的實例數(shù)目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。
1 經(jīng)常被修改的數(shù)據(jù)
2 財務(wù)數(shù)據(jù),絕對不允許出現(xiàn)并發(fā)
3 與其他應(yīng)用共享的數(shù)據(jù)。
Hibernater 的二級緩存是一個插件,下面是幾種常用的緩存插件:
l EhCache:可作為進(jìn)程范圍的緩存,存放數(shù)據(jù)的物理介質(zhì)可以是內(nèi)存或硬盤,對Hibernate的查詢緩存提供了支持。
l OSCache:可作為進(jìn)程范圍的緩存,存放數(shù)據(jù)的物理介質(zhì)可以是內(nèi)存或硬盤,提供了豐富的緩存數(shù)據(jù)過期策略,對Hibernate的查詢緩存提供了支持。
l SwarmCache:可作為群集范圍內(nèi)的緩存,但不支持Hibernate的查詢緩存。
l JBossCache:可作為群集范圍內(nèi)的緩存,支持事務(wù)型并發(fā)訪問策略,對Hibernate的查詢緩存提供了支持。
1) 選擇需要使用二級緩存的持久化類,設(shè)置它的命名緩存的并發(fā)訪問策略。這是最值得認(rèn)真考慮的步驟。
2) 選擇合適的緩存插件,然后編輯該插件的配置文件。
1. 首先設(shè)置EhCache,建立配置文件ehcache.xml,默認(rèn)的位置在class-path,可以放到你的src目錄下:
<ehcache>
<diskStore path="c:\\ehcache\"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 設(shè)置Category類的緩存的數(shù)據(jù)過期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- 設(shè)置Category類的products集合的緩存的數(shù)據(jù)過期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category.products"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="org.qiujy.domain.cachedemo.Product"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
</ehcache>
配置的元素說明:
<diskStore>
設(shè)置緩存數(shù)據(jù)文件的存放目錄
<defaultCache>
設(shè)置緩存的默認(rèn)數(shù)據(jù)過期策略
<cache>
設(shè)定具體的命名緩存的數(shù)據(jù)過期策略
每個命名緩存代表一個緩存區(qū)域,每個緩存區(qū)域有各自的數(shù)據(jù)過期策略。命名緩存機制使得用戶能夠在每個類以及類的每
2. 在Hibernate配置文件中設(shè)置:
<hibernate-configuration>
<session-factory>……<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><property name="cache.use_second_level_cache">true</property>……</session-factory></hibernate-configuration> 此外,可以把cache.use_second_level_cache設(shè)置為false關(guān)閉所有的hibernate二級緩存。但此屬性對指定<cache>的類缺省為true。
3. 為了使用二級緩存,需要在每一個Hibernate Entity上配置。
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
}
@Cache(
CacheConcurrencyStrategy usage(); (1)
String region()
String include()
)
(1) usage: 提供緩存對象的事務(wù)隔離機制,可選值有以下幾種
(NONE, READ_ONLY, NONSTRICT_READ_WRITE(非嚴(yán)格讀寫), READ_WRITE, TRANSACTIONAL)
(2) region (optional): 指定緩存的區(qū)域,默認(rèn)是類的全限定名。利用緩存區(qū)域,可以更精確的指定每個區(qū)域的緩存超前策略。如果指定了緩存區(qū)域前綴(在hibernate.cfg.xml中設(shè)置cache.region_prefix屬性為一個字符串),則所有的緩存區(qū)域名前將加上這個前綴。
(3) include (optional): all to include all properties, non-lazy to only include non lazy properties (default all).
如果不是使用annotation的話,則是在Hbm文件中添加cache usage="read-only"
http://blog.163.com/seara520@126/blog/static/7206930420102232340810/