緩存是關(guān)于應(yīng)用程序性能的優(yōu)化,降低了應(yīng)用程序?qū)ξ锢頂?shù)據(jù)源訪問的頻次,從而提高應(yīng)用程序的運行性能。
緩存對 Hibernate 來說也是重要的,它使用了如下解釋的多級緩存方案:
第一級緩存是 Session 緩存并且是一種強制性的緩存,所有的要求都必須通過它。Session 對象在它自己的權(quán)利之下,在將它提交給數(shù)據(jù)庫之前保存一個對象。
如果你對一個對象發(fā)出多個更新,Hibernate 會嘗試盡可能長地延遲更新來減少發(fā)出的 SQL 更新語句的數(shù)目。如果你關(guān)閉 session,所有緩存的對象丟失,或是存留,或是在數(shù)據(jù)庫中被更新。
第二級緩存是一種可選擇的緩存并且第一級緩存在任何想要在第二級緩存中找到一個對象前將總是被詢問。第二級緩存可以在每一個類和每一個集合的基礎(chǔ)上被安裝,并且它主要負責(zé)跨會話緩存對象。
任何第三方緩存可以和 Hibernate 一起使用。org.hibernate.cache.CacheProvider 接口被提供,它必須實現(xiàn)來給 Hibernate 提供一個緩存實現(xiàn)的解決方法。
Hibernate 也實現(xiàn)了一個和第二級緩存密切集成的查詢結(jié)果集緩存。
這是一個可選擇的特點并且需要兩個額外的物理緩存區(qū)域,它們保存著緩存的查詢結(jié)果和表單上一次更新時的時間戳。這僅對以同一個參數(shù)頻繁運行的查詢來說是有用的。
Hibernate 使用默認的一級緩存并且你不用使用一級緩存。讓我們直接看向可選的二級緩存。不是所有的類從緩存中獲益,所以能關(guān)閉二級緩存是重要的。
Hibernate 的二級緩存通過兩步設(shè)置。第一,你必須決定好使用哪個并發(fā)策略。之后,你使用緩存提供程序來配置緩存到期時間和物理緩存屬性。
一個并發(fā)策略是一個中介,它負責(zé)保存緩存中的數(shù)據(jù)項和從緩存中檢索它們。如果你將使用一個二級緩存,你必須決定,對于每一個持久類和集合,使用哪一個并發(fā)策略。
如果我們將為我們的 Employee 類使用二級緩存,讓我們使用 read-write 策略來添加需要告訴 Hibernate 來緩存 Employee 實例的映射元素。
<?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ā)策略。
在考慮你將為你的緩存候選類所使用的并發(fā)策略后你的下一步是挑選一個緩存提供者。Hibernate 讓你為整個應(yīng)用程序選擇一個單獨的緩存提供者。
S.N. | 緩存名 | 描述 |
---|---|---|
1 | EHCache | 它能在內(nèi)存或硬盤上緩存并且集群緩存,而且它支持可選的 Hibernate 查詢結(jié)果緩存。 |
2 | OSCache | 支持在一個單獨的 JVM 中緩存到內(nèi)存和硬盤,同時有豐富的過期策略和查詢緩存支持。 |
3 | warmCache | 一個基于 JGroups 的聚集緩存。它使用集群失效但是不支持 Hibernate 查詢緩存。 |
4 | JBoss Cache | 一個也基于 JGroups 多播庫的完全事務(wù)性的復(fù)制集群緩存。它支持復(fù)制或者失效,同步或異步通信,樂觀和悲觀鎖定。Hibernate 查詢緩存被支持。 |
每一個緩存提供者都不和每個并發(fā)策略兼容。以下的兼容性矩陣將幫助你選擇一個合適的組合。
策略/提供者 | 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 配置文件中指定一個緩存提供者。我們選擇 EHCache 作為我們的二級緩存提供者:
<?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 類的 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 類的二級緩存并且 Hibernate 現(xiàn)在能命中緩存無論是你導(dǎo)航到 Employee 時或是當你通過標識符上傳 Employee 時。
你應(yīng)該為每個類分析你所有的類并選擇合適的緩存策略。有時候,二級緩存可能使應(yīng)用程序的表現(xiàn)下降。所以首先不允許緩存用基準程序測試你的應(yīng)用程序,然后開啟合適的緩存,之后檢測表現(xiàn)是推薦的。如果緩存不提升系統(tǒng)表現(xiàn)那么支持任何類型的緩存都是沒有意義的。
為了使用查詢緩存,你必須首先使用配置文件中的 hibernate.cache.use_query_cache="true" 屬性激活它。通過設(shè)置這個屬性為真,你使得 Hibernate 創(chuàng)建內(nèi)存中必要的緩存來保存查詢和標識符集。
然后,為了使用查詢緩存,你使用 Query 類的 setCacheable(Boolean) 方法。例如:
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();
Hibernate 通過緩存區(qū)域的概念也支持非常細粒度的緩存支持。一個緩存區(qū)域是被給予名字的緩存部分。
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();
這段代碼使用方法來告訴 Hibernate 存儲和尋找緩存 employee 區(qū)域的查詢。
更多建議: