Hibernate ehcache配置二級緩存
?
?
1、首先設置EhCache,建立配置文件ehcache.xml,默認的位置在class-path,可以放到你的src目錄下:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"<!-- 緩存最大數(shù)目 -->
eternal="false"<!-- 緩存是否持久 -->
overflowToDisk="true"<!-- 是否保存到磁盤,當系統(tǒng)當機時-->
timeToIdleSeconds="300"<!-- 當緩存閑置n秒后銷毀 -->
timeToLiveSeconds="180"<!-- 當緩存存活n秒后銷毀-->
diskPersistent="false"
diskExpiryThreadIntervalSeconds= "120"/>
</ehcache>
2、在Hibernate配置文件中設置:
<!-- 設置Hibernate的緩存接口類,這個類在Hibernate包中 -->
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<!-- 是否使用查詢緩存 -->
<property name="hibernate.cache.use_query_cache">true</property>
如果使用spring調(diào)用Hibernate的sessionFactory的話,這樣設置:
<!--HibernateSession工廠管理 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="datasource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
? <prop key="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
</props>
</property>
<property name="mappingDirectoryLocations">
<list>
<value>/WEB-INF/classes/cn/rmic/manager/hibernate/</value>
</list>
</property>
</bean>
說明一下:如果不設置“查詢緩存”,那么hibernate只會緩存使用load()方法獲得的單個持久化對象,如果想緩存使用findall()、
list()、Iterator()、createCriteria()、createQuery()等方法獲得的數(shù)據(jù)結果集的話,就需要設置
hibernate.cache.use_query_cache true 才行
3、在Hbm文件中添加<cache usage="read-only"/>
4、如果需要“查詢緩存”,還需要在使用Query或Criteria()時設置其setCacheable(true);屬性
5、實踐出真知,給一段測試程序,如果成功的話第二次查詢時不會讀取數(shù)據(jù)庫
package cn.rmic.hibernatesample;
import java.util.List;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import cn.rmic.hibernatesample.hibernate.HibernateSessionFactory;
import cn.rmic.manager.po.Resources;
public class testCacheSelectList ...{
public static void main(String[] args) ...{
Session s=HibernateSessionFactory.getSession();
Criteria c=s.createCriteria(Resources.class);
c.setCacheable(true);
List l=c.list();
Resources resources=(Resources)l.get(0);
System.out.println("-1-"+resources.getName());
HibernateSessionFactory.closeSession();
try ...{
Thread.sleep(5000);
} catch (InterruptedException e) ...{
// TODO Auto-generated catch block
e.printStackTrace();
}
s=HibernateSessionFactory.getSession();
c=s.createCriteria(Resources.class);
c.setCacheable(true);
l=c.list();
resources=(Resources)l.get(0);
System.out.println("-2-"+resources.getName());
HibernateSessionFactory.closeSession();
}
}
?
1. 在Hibernate配置文件中設置:
????
<!--
?Hibernate?SessionFactory?
-->
????
<
bean?id
=
"
sessionFactory
"
?
class
=
"
org.springframework.orm.hibernate3.LocalSessionFactoryBean
"
>
????????
<
property?name
=
"
dataSource
"
?ref
=
"
dataSource
"
/>
????????
<
property?name
=
"
mappingResources
"
>
????????
<
list
>
????????????
<
value
>
com
/
ouou
/
model
/
Videos.hbm.xml
</
value
>
???
?????????
</
list
>
?????????
</
property
>
????????
<
property?name
=
"
hibernateProperties
"
>
????????????
<
props
>
????????????????
<
prop?key
=
"
hibernate.dialect
"
>
org.hibernate.dialect.MySQLDialect
</
prop
>
????????????????
<
prop?key
=
"
hibernate.current_session_context_class
"
>
thread
</
prop
>
????????????????
<
prop?key
=
"
hibernate.cglib.use_reflection_optimizer
"
>
false
</
prop
>
????????????????
<
prop?key
=
"
hibernate.query.substitutions
"
>
true
?
'
Y
'
,?
false
?
'
N
'
</
prop
>
????????????????
<!--
add?ehcache
-->
????????????????
<
prop?key
=
"
hibernate.cache.provider_class
"
>
org.hibernate.cache.EhCacheProvider
</
prop
>
????????????????
<
prop?key
=
"
hibernate.cache.use_query_cache
"
>
false
</
prop
><!--
?是否使用查詢緩存?
-->
????????????????
<!--
????????????????
<
prop?key
=
"
hibernate.cache.provider_configuration_file_resource_path
"
>/
ehcache.xml
</
prop
>
????????????????
<
prop?key
=
"
hibernate.show_sql
"
>
true
</
prop
>
????????????????
-->
????????????????
<!--<
prop?key
=
"
hibernate.transaction.auto_close_session
"
>
true
</
prop
>-->
????????????????
<
prop?key
=
"
connection.provider_class
"
>
org.hibernate.connection.C3P0ConnectionProvider
</
prop
>
????????????????
<!--
?Create
/
update?the?database?tables?automatically?when?the?JVM?starts?up
?????????????????
<
prop?key
=
"
hibernate.hbm2ddl.auto
"
>
update
</
prop
>
?
-->
????????????????
<!--
?Turn?batching?off?
for
?better?error?messages?under?PostgreSQL?
-->
????????????????
<
prop?key
=
"
hibernate.jdbc.batch_size
"
>
25
</
prop
>
????????????????
<!--
????????????????
<
prop?key
=
"
hibernate.connection.pool_size
"
>
10
</
prop
>
????????????????
-->
????????????
</
props
>
????????
</
property
>
????
</
bean
>
???
如果不設置“查詢緩存”,那么hibernate只會緩存使用load()方法獲得的單個持久化對象,如果想緩存使用findall()、
list()、Iterator()、createCriteria()、createQuery()等方法獲得的數(shù)據(jù)結果集的話,就需要設置
hibernate.cache.use_query_cache true 才行
2.首先設置EhCache,建立配置文件ehcache.xml,默認的位置在class-path,可以放到你的src目錄下:
?
<
ehcache
>
????
<!--
?Sets?the?path?to?the?directory?where?cache?.data?files?are?created.

?????If?the?path?is?a?Java?System?Property?it?is?replaced?by
?????its?value?in?the?running?VM.
?????The?following?properties?are?translated:
?????user.home?
-
?User
'
s?home?directory
?????user.dir?
-
?User
'
s?current?working?directory
?????java.io.tmpdir?
-
?Default?temp?file?path?
-->
?????
<!--<
diskStore?path
=
"
java.io.tmpdir
"
/>-->
?????
<
diskStore?path
=
"
/data/ehcache
"
/>
????
<!--
Default?Cache?configuration.?These?will?applied?to?caches?programmatically?created?through
????????the?CacheManager.

????????The?following?attributes?are?required:

????????maxElementsInMemory????????????
-
?Sets?the?maximum?number?of?objects?that?will?be?created?in?memory
????????eternal?????????????????????????????????????
-
?Sets?whether?elements?are?eternal.?If?eternal,??timeouts?are?
?????????????????????????????????????????? ? ? ? ? ? ?????? ignored?and?the?element?is?never?expired.
????????overflowToDisk??????????????????????
-
?Sets?whether?elements?can?overflow?to?disk?when?the?in
-
memory?cache
????????????????????????????????????????????????????????has?reached?the?maxInMemory?limit.

????????The?following?attributes?are?optional:
????????timeToIdleSeconds???????????
-
?Sets?the?time?to?idle?
for
?an?element?before?it?expires.
??????????????????????????????????????????????????????? i.e.?The?maximum?amount?of?time?between?accesses?before?an
???????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? element?expires?Is?only?used?
if
?the?element?is?not?eternal.
????????????????????????????????????????????????????????Optional?attribute.?A?value?of?
0
?means?that?an?Element?can?idle
??????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???
for
?infinity.The?
default
?value?is?
0
.
????????timeToLiveSeconds?????????????
-
?Sets?the?time?to?live?
for
?an?element?before?it?expires.
???????????????????????????????????????????????????? ? ? i.e.?The?maximum?time?between?creation?time?and?when?an?element?
?????????????????????????????????????????????????????????expires.??Is?only?used?
if
?the?element?is?not?eternal.
?????????????????????????????????????????????????????????Optional?attribute.?A?value?of?
0
?means?that?and?Element?can?live
???????????????????????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???
for
?infinity.
????????????????????????????????????????????????????????The?
default
?value?is?
0
.
????????diskPersistent???????????????????????????
-
?Whether?the?disk?store?persists?between?restarts?of?the?Virtual
???????????????????????????????????????????????????????????? Machine.
?????????????????????????????????????????????????????????The?
default
?value?is?
false
.
????????diskExpiryThreadIntervalSeconds???
-
?The?number?of?seconds?between?runs?of?the?disk?expiry?thread.?
?????????????????????????????????????????????????????????The?
default
?value??is?
120
?seconds.
????????
-->
????
<
defaultCache
????????maxElementsInMemory
=
"
10000
"
????????eternal
=
"
false
"
????????overflowToDisk
=
"
true
"
????????timeToIdleSeconds
=
"
120
"
????????timeToLiveSeconds
=
"
120
"
????????diskPersistent
=
"
false
"
????????diskExpiryThreadIntervalSeconds
=
"
120
"
/>
????
<
cache?name
=
"
org.hibernate.cache.UpdateTimestampsCache
"
?maxElementsInMemory
=
"
5000
"
?
?????eternal
=
"
true
"
?overflowToDisk
=
"
true
"
/>
????
<
cache?name
=
"
org.hibernate.cache.StandardQueryCache
"
?maxElementsInMemory
=
"
5
"
?eternal
=
"
false
"
????timeToLiveSeconds
=
"
120
"
?overflowToDisk
=
"
true
"
/>
????
<
cache?name
=
"
userCache
"
?maxElementsInMemory
=
"
100000
"
?eternal
=
"
false
"
?timeToIdleSeconds
=
??????? "
600
"
?? timeToLiveSeconds
=
"
600
"
?overflowToDisk
=
"
false
"
?diskPersistent
=
"
false
"
/>
????
<
cache?name
=
"
com.ouou.webapp.util.OuouMethodIntecepter
"
?maxElementsInMemory
=
"
100000
"
?
????eternal
=
"
false
"
?timeToIdleSeconds
=
"
600
"
?timeToLiveSeconds
=
"
600
"
?overflowToDisk
=
"
false
"
????diskPersistent
=
"
false
"
/>
????
<
cache?name
=
"
bbcode
"
?maxElementsInMemory
=
"
100000
"
?eternal
=
"
false
"
?timeToIdleSeconds
=
"
600
"
????timeToLiveSeconds
=
"
600
"
?
????overflowToDisk
=
"
false
"
?diskPersistent
=
"
false
"
/>
????
<
cache?name
=
"
com.ouou.model.Videos
"
?maxElementsInMemory
=
"
10000
"
??eternal
=
"
false
"
?
????overflowToDisk
=
"
false
"
?timeToIdleSeconds
=
"
120
"
?timeToLiveSeconds
=
"
120
"
?diskPersistent
=
"
false
"
/>
????
<
cache?name
=
"
com.ouou.model.Tags
"
?maxElementsInMemory
=
"
10000
"
??eternal
=
"
false
"
????overflowToDisk
=
"
false
"
?timeToIdleSeconds
=
"
120
"
?timeToLiveSeconds
=
"
120
"
?diskPersistent
=
"
false
"
/>
</
ehcache
>
以com.ouou.model.Videos為例子
在Videos.hbm.xml中配置:
<class name="Videos" table="TEST" lazy="false">
? <cache usage="read-write" region="ehcache.xml中的name的屬性值"/>注意:這一句需要緊跟在class標簽下面,其他位置無效。
hbm文件查找cache方法名的策略:如果不指定hbm文件中的region="ehcache.xml中的name的屬性值",則使用name名為com.ouou.model.Videos的cache,
如果不存在與類名匹配的cache名稱,則用defaultCache。
如果Videos包含set集合,則需要另行指定其cache
例如Videos包含Tags集合,則需要
添加如下配置到ehcache.xml中
<cache name="com.ouou.model.Tags"
??????? maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
??????? timeToLiveSeconds="120" overflowToDisk="false" />
另,針對查詢緩存的配置如下:
<cache name="org.hibernate.cache.UpdateTimestampsCache"
??????? maxElementsInMemory="5000"
??????? eternal="true"
??????? overflowToDisk="true"/>
<cache name="org.hibernate.cache.StandardQueryCache"
??????? maxElementsInMemory="10000"
??????? eternal="false"
??????? timeToLiveSeconds="120"
??????? overflowToDisk="true"/>
3、 選擇緩存策略依據(jù):
<cache? usage="transactional|read-write|nonstrict-read-write|read-only" (1)/>
ehcache不支持transactional,其他三種可以支持。
read-only:無需修改, 那么就可以對其進行只讀 緩存,注意,在此策略下,如果直接修改數(shù)據(jù)庫,即使能夠看到前臺顯示效果,
但是將對象修改至cache中會報error,cache不會發(fā)生作用。另:刪除記錄會報錯,因為不能在read-only模式的對象從cache中刪除。
read-write:需要更新數(shù)據(jù),那么使用讀/寫緩存 比較合適,前提:數(shù)據(jù)庫不可以為serializable transaction isolation level
(序列化事務隔離級別)
nonstrict-read-write:只偶爾需要更新數(shù)據(jù)(也就是說,兩個事務同時更新同一記錄的情況很不常見),也不需要十分嚴格的事務隔離,
那么比較適合使用非嚴格讀/寫緩存策略。
4、 調(diào)試時候使用log4j的log4j.logger.org.hibernate.cache=debug,更方便看到ehcache的操作過程,主要用于調(diào)試過程,實際應用發(fā)布時候,請注釋掉,以免影響性能。
5、 使用ehcache,打印sql語句是正常的,因為query cache設置為true將會創(chuàng)建兩個緩存區(qū)域:一個用于保存查詢結果集 (
org.hibernate.cache.StandardQueryCache);另一個則用于保存最近查詢的一系列表的時間戳(org.hibernate.cache.UpdateTimestampsCache)。
請注意:在查詢緩存中,它并不緩存結果集中所包含的實體的確切狀態(tài);它只緩存這些實體的標識符屬性的值、以及各值類型的結果。
需要將打印sql語句與最近的cache內(nèi)容相比較,將不同之處修改到cache中,所以查詢緩存通常會和二級緩存一起使用。
?
Ehcache的配置說明
<ehcache>
<!--
磁盤存儲配置:
用來指定緩存在磁盤上的存儲位置。可以使用JavaVM環(huán)境變量(user.home, user.dir, java.io.tmpdir)
-->
<diskStore path = "/var/apps/cache/" />
<!--
指定CacheManagerEventListenerFactory,這個對象在緩存添加的時候會得到相應的通知
CacheManagerEventListenerFactory的屬性
*class - CacheManagerEventListenerFactory的一個實現(xiàn)類
*properties - CacheManagerEventListenerFactory的屬性值,以逗號(,)分割多個屬性
如果沒有實現(xiàn)類被指定,則系統(tǒng)不創(chuàng)建CacheManager的監(jiān)聽器,沒有默認值
-->
<cacheManagerEventListenerFactory class="" properties="" />
<!--
在進行分布式緩存的應用時候需要指定CacheManagerPeerProviderFactory,
用來生成CacheManagerPeerProvider的實例,以便和集群中的其他CacheManager通信。
*class -CacheManagerPeerProviderFactory的一個實現(xiàn)類
*properties - CacheManagerPeerProviderFactory的屬性值,以逗號(,)分割多個屬性
Ehcache內(nèi)建了2種基于RMI分布系統(tǒng)的通信策略:
*automatic - 使用多播組。在一個節(jié)點加入或者推出集群的時候自動感應
*manual - 硬編碼方式
目前的awf中不考慮分布緩存
-->
<cacheManagerPeerListenerFactory class="" properties="" />
<!--
緩存配置。
以下屬性是必須的:
name - cache的標識符,在一個CacheManager中必須唯一
maxElementsInMemory - 在內(nèi)存中緩存的element的最大數(shù)目
maxElementsOnDisk - 在磁盤上緩存的element的最大數(shù)目
eternal - 設定緩存的elements是否有有效期。如果為true,timeouts屬性被忽略
overflowToDisk - 設定當內(nèi)存緩存溢出的時候是否將過期的element緩存到磁盤上
以下屬性是可選的:
timeToIdleSeconds - 緩存element在過期前的空閑時間。默認為0,表示可空閑無限時間.
??????? (如果指定了這個時間,是否在被hit的前超過了這個時間就會被remove?在內(nèi)存緩存數(shù)目超限之前不會被remove)
timeToLiveSeconds - 緩存element的有效生命期。這個類似于timeouts,默認為0,不過期
??????? (是否通常情況下應該大于等于timeToIdleSeconds,小于會如何?idle時間也會減小和這個數(shù)值一樣)
diskPersistent - 在VM重啟的時候是否持久化磁盤緩存,默認是false。
??????? (測試一下true的情況?重載vm的時候會從磁盤進行序列化到對象)
diskExpiryThreadIntervalSeconds - 磁盤緩存的清理線程運行間隔,默認是120秒.
??????? (測試一下0的時候會如何)
memoryStoreEvictionPolicy - 當內(nèi)存緩存達到最大,有新的element加入的時候,
??????? 移除緩存中element的策略。默認是LRU,可選的有LFU和FIFO
可對緩存中的element配置諸如監(jiān)聽器和加載器。Ehcahe內(nèi)建了一些
*cacheEventListenerFactory - 監(jiān)聽緩存中element的put, remove, update和expire事件
*bootstrapCacheLoaderFactory - 啟動時加載緩存的element
每個用來做分布式緩存都必須設定element的事件監(jiān)聽器,用來在各個CacheManager節(jié)點復制消息。
Ehcache內(nèi)建了基于RMI的實現(xiàn) - RMICacheReplicatorFactory
??? <cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
??????? properties="replicateAsynchronouly=true,
??????? replicatePuts=true,
??????? replicateUpdates=true,
??????? replicateUpdateViaCopy=true,
??????? replicateRemovals=true" />
-->
<cache .... />
<!--
默認的Cache配置。用來實現(xiàn)CacheManager.add(String cacheName)創(chuàng)建的緩存
-->
<defaultCache maxElementsInMemory="10000" eternal="false"
??????? timeToIdleSeconds="120" timeToLiveSeconds="120"
??????? overflowToDisk="true" maxElementsOnDisk="1000000"
??????? diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
??????? memoryStoreEvictionPolicy="LRU"
??????? />
</ehcache>