鍍金池/ 教程/ Java/ 緩存
例子
注釋
映射類(lèi)型
ORM 概覽
環(huán)境
標(biāo)準(zhǔn)查詢(xún)
原生 SQL
持久化類(lèi)
查詢(xún)語(yǔ)言
配置
批處理
緩存
架構(gòu)
會(huì)話(huà)
映射文件
O/R 映射
簡(jiǎn)介
攔截器

緩存

緩存是關(guān)于應(yīng)用程序性能的優(yōu)化,降低了應(yīng)用程序?qū)ξ锢頂?shù)據(jù)源訪問(wèn)的頻次,從而提高應(yīng)用程序的運(yùn)行性能。

緩存對(duì) Hibernate 來(lái)說(shuō)也是重要的,它使用了如下解釋的多級(jí)緩存方案:

http://wiki.jikexueyuan.com/project/hibernate/images/hibernate_cache.jpg" alt="image" />

一級(jí)緩存

第一級(jí)緩存是 Session 緩存并且是一種強(qiáng)制性的緩存,所有的要求都必須通過(guò)它。Session 對(duì)象在它自己的權(quán)利之下,在將它提交給數(shù)據(jù)庫(kù)之前保存一個(gè)對(duì)象。

如果你對(duì)一個(gè)對(duì)象發(fā)出多個(gè)更新,Hibernate 會(huì)嘗試盡可能長(zhǎng)地延遲更新來(lái)減少發(fā)出的 SQL 更新語(yǔ)句的數(shù)目。如果你關(guān)閉 session,所有緩存的對(duì)象丟失,或是存留,或是在數(shù)據(jù)庫(kù)中被更新。

二級(jí)緩存

第二級(jí)緩存是一種可選擇的緩存并且第一級(jí)緩存在任何想要在第二級(jí)緩存中找到一個(gè)對(duì)象前將總是被詢(xún)問(wèn)。第二級(jí)緩存可以在每一個(gè)類(lèi)和每一個(gè)集合的基礎(chǔ)上被安裝,并且它主要負(fù)責(zé)跨會(huì)話(huà)緩存對(duì)象。

任何第三方緩存可以和 Hibernate 一起使用。org.hibernate.cache.CacheProvider 接口被提供,它必須實(shí)現(xiàn)來(lái)給 Hibernate 提供一個(gè)緩存實(shí)現(xiàn)的解決方法。

查詢(xún)層次緩存

Hibernate 也實(shí)現(xiàn)了一個(gè)和第二級(jí)緩存密切集成的查詢(xún)結(jié)果集緩存。

這是一個(gè)可選擇的特點(diǎn)并且需要兩個(gè)額外的物理緩存區(qū)域,它們保存著緩存的查詢(xún)結(jié)果和表單上一次更新時(shí)的時(shí)間戳。這僅對(duì)以同一個(gè)參數(shù)頻繁運(yùn)行的查詢(xún)來(lái)說(shuō)是有用的。

第二級(jí)緩存

Hibernate 使用默認(rèn)的一級(jí)緩存并且你不用使用一級(jí)緩存。讓我們直接看向可選的二級(jí)緩存。不是所有的類(lèi)從緩存中獲益,所以能關(guān)閉二級(jí)緩存是重要的。

Hibernate 的二級(jí)緩存通過(guò)兩步設(shè)置。第一,你必須決定好使用哪個(gè)并發(fā)策略。之后,你使用緩存提供程序來(lái)配置緩存到期時(shí)間和物理緩存屬性。

并發(fā)策略

一個(gè)并發(fā)策略是一個(gè)中介,它負(fù)責(zé)保存緩存中的數(shù)據(jù)項(xiàng)和從緩存中檢索它們。如果你將使用一個(gè)二級(jí)緩存,你必須決定,對(duì)于每一個(gè)持久類(lèi)和集合,使用哪一個(gè)并發(fā)策略。

  • Transactional:為主讀數(shù)據(jù)使用這個(gè)策略,在一次更新的罕見(jiàn)狀況下并發(fā)事務(wù)阻止過(guò)期數(shù)據(jù)是關(guān)鍵的。
  • Read-write:為主讀數(shù)據(jù)再一次使用這個(gè)策略,在一次更新的罕見(jiàn)狀況下并發(fā)事務(wù)阻止過(guò)期數(shù)據(jù)是關(guān)鍵的。
  • Nonstrict-read-write:這個(gè)策略不保證緩存和數(shù)據(jù)庫(kù)之間的一致性。如果數(shù)據(jù)幾乎不改變并且過(guò)期數(shù)據(jù)不是很重要,使用這個(gè)策略。
  • Read-only:一個(gè)適合永不改變數(shù)據(jù)的并發(fā)策略。只為參考數(shù)據(jù)使用它。

如果我們將為我們的 Employee 類(lèi)使用二級(jí)緩存,讓我們使用 read-write 策略來(lái)添加需要告訴 Hibernate 來(lái)緩存 Employee 實(shí)例的映射元素。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name="Employee" table="EMPLOYEE">
      <meta attribute="class-description">
         This class contains the employee detail. 
      </meta>
      <cache usage="read-write"/>
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <property name="firstName" column="first_name" type="string"/>
      <property name="lastName" column="last_name" type="string"/>
      <property name="salary" column="salary" type="int"/>
   </class>
</hibernate-mapping>

usage="read-write" 參數(shù)告訴 Hibernate 為定義的緩存使用 read-write 并發(fā)策略。

緩存提供者

在考慮你將為你的緩存候選類(lèi)所使用的并發(fā)策略后你的下一步是挑選一個(gè)緩存提供者。Hibernate 讓你為整個(gè)應(yīng)用程序選擇一個(gè)單獨(dú)的緩存提供者。

S.N. 緩存名 描述
1 EHCache 它能在內(nèi)存或硬盤(pán)上緩存并且集群緩存,而且它支持可選的 Hibernate 查詢(xún)結(jié)果緩存。
2 OSCache 支持在一個(gè)單獨(dú)的 JVM 中緩存到內(nèi)存和硬盤(pán),同時(shí)有豐富的過(guò)期策略和查詢(xún)緩存支持。
3 warmCache 一個(gè)基于 JGroups 的聚集緩存。它使用集群失效但是不支持 Hibernate 查詢(xún)緩存。
4 JBoss Cache 一個(gè)也基于 JGroups 多播庫(kù)的完全事務(wù)性的復(fù)制集群緩存。它支持復(fù)制或者失效,同步或異步通信,樂(lè)觀和悲觀鎖定。Hibernate 查詢(xún)緩存被支持。

每一個(gè)緩存提供者都不和每個(gè)并發(fā)策略兼容。以下的兼容性矩陣將幫助你選擇一個(gè)合適的組合。

策略/提供者 Read-only Nonstrictread-write Read-write Transactional
EHCache X X X
OSCache X X X
SwarmCache X X
JBoss Cache X X

你將在 hibernate.cfg.xml 配置文件中指定一個(gè)緩存提供者。我們選擇 EHCache 作為我們的二級(jí)緩存提供者:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
   </property>
   <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
   </property>

   <!-- Assume students is the database name -->
   <property name="hibernate.connection.url">
      jdbc:mysql://localhost/test
   </property>
   <property name="hibernate.connection.username">
      root
   </property>
   <property name="hibernate.connection.password">
      root123
   </property>
   <property name="hibernate.cache.provider_class">
      org.hibernate.cache.EhCacheProvider
   </property>

   <!-- List of XML mapping files -->
   <mapping resource="Employee.hbm.xml"/>

</session-factory>
</hibernate-configuration>

現(xiàn)在,你需要指定緩存區(qū)域的屬性。EHCache 有它自己的配置文件,ehcache.xml,它應(yīng)該在應(yīng)用程序的 CLASSPATH 中。Employee 類(lèi)的 ehcache.xml 緩存配置像如下這樣:

<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>

<cache name="Employee"
maxElementsInMemory="500"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>

就是這樣,現(xiàn)在我們有 Employee 類(lèi)的二級(jí)緩存并且 Hibernate 現(xiàn)在能命中緩存無(wú)論是你導(dǎo)航到 Employee 時(shí)或是當(dāng)你通過(guò)標(biāo)識(shí)符上傳 Employee 時(shí)。

你應(yīng)該為每個(gè)類(lèi)分析你所有的類(lèi)并選擇合適的緩存策略。有時(shí)候,二級(jí)緩存可能使應(yīng)用程序的表現(xiàn)下降。所以首先不允許緩存用基準(zhǔn)程序測(cè)試你的應(yīng)用程序,然后開(kāi)啟合適的緩存,之后檢測(cè)表現(xiàn)是推薦的。如果緩存不提升系統(tǒng)表現(xiàn)那么支持任何類(lèi)型的緩存都是沒(méi)有意義的。

查詢(xún)層次緩存

為了使用查詢(xún)緩存,你必須首先使用配置文件中的 hibernate.cache.use_query_cache="true" 屬性激活它。通過(guò)設(shè)置這個(gè)屬性為真,你使得 Hibernate 創(chuàng)建內(nèi)存中必要的緩存來(lái)保存查詢(xún)和標(biāo)識(shí)符集。

然后,為了使用查詢(xún)緩存,你使用 Query 類(lèi)的 setCacheable(Boolean) 方法。例如:

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

Hibernate 通過(guò)緩存區(qū)域的概念也支持非常細(xì)粒度的緩存支持。一個(gè)緩存區(qū)域是被給予名字的緩存部分。

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

這段代碼使用方法來(lái)告訴 Hibernate 存儲(chǔ)和尋找緩存 employee 區(qū)域的查詢(xún)。

上一篇:攔截器下一篇:會(huì)話(huà)