EZLippi-浮生志

Hibernate缓存配置笔记

Hibernate中提供了两级Cache,第一级别的缓存是Session级别的缓存,这一级别的缓存由hibernate管理的,一般情况下无需进行干预;第二级别的缓存是SessionFactory级别的缓存,它是属于进程范围或群集范围的缓存,这一级别的缓存可以进行配置和更改,并且可以动态加载和卸载。 Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。

一级缓存和二级缓存的要点



使用二级缓存

这里以EhCache作为二级缓存的插件为例介绍Hibernate二级缓存的配置。

(1)打开二级缓存:

为Hibernate配置二级缓存:

在主配置文件中hibernate.cfg.xml :

Hibernate3.3以上:

<property     name="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</property>

Hibernate4.0以上,使用org.hibernate.cache.ehcache.EhCacheRegionFactory代替net.sf.ehcache.hibernate.EhCacheRegionFactory

<!--二级缓存-->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!--查询缓存-->
<property name="hibernate.cache.use_query_cache">true</property>
在查询定义的地方加入setCacheable(true),这次查询就被缓存起来了 

(2)配置ehcache.xml

<ehcache>
<!--缓存到硬盘的路径-->
<diskStore path="/home/lippi/ehcache"/>
<defaultCache
maxElementsInMemory="200"<!-- 最多缓存多少个对象 -->
eternal="false"<!-- 内存中的对象是否永远不变 -->
timeToIdleSeconds="50"<!--空闲了多长时间,超过这个时间清除 -->
timeToLiveSeconds="60"<!--总共存活时间 -->
overflowToDisk="true"<!--内存中溢出就放到硬盘上 -->
/>

<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"  
       maxElementsInMemory="5000"   
       eternal="true"   
       overflowToDisk="true" />  
<cache name="org.hibernate.cache.internal.StandardQueryCache"  
       maxElementsInMemory="10000"   
       eternal="false"   
       timeToLiveSeconds="120"  
       overflowToDisk="true" /> 
<!--
java文件注解查找cache方法名的策略:如果不指定java文件注解中的    region="ehcache.xml中的name的属性值", 则使用name名为全限定包名, 如果不存在与类名匹配的cache名称, 则用 defaultCache,如果类中包含set集合, 则需要另行指定其cache指定缓存的对象,缓存哪一个实体类,下面出现的的属性覆盖上面出现的,没出现的继承上面的。
-->
<cache name="com.lippi.hibernate.pojos.Order"
maxElementsInMemory="200"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>

(3)使用二级缓存需要在实体类中加入注解:

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

Load默认使用二级缓存,就是当查一个对象的时候,它先会去二级缓存里面去找,如果找到了就不去数据库中查了。

Iterator默认的也会使用二级缓存,有的话就不去数据库里面查了,不发送select语句了。

List默认的往二级缓存中加数据,假如有一个query,把数据拿出来之后会放到二级缓存,但是执行查询的时候不会到二级缓存中查,会在数据库中查。原因每个query中查询条件不一样。

(4)也可以在需要被缓存的对象中hbm文件中的标签下添加一个子标签:

<hibernate-mapping>
<class name="com.lippi.hibernate.pojos.Order" table="Orders">
<cache usage="read-only"/>
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>
<property name="orderNumber" column="orderNumber" type="string"></property>
<property name="cost" column="cost" type="integer"></property>
<many-to-one name="customer" class="com.lippi.hibernate.pojos.Customer"
column="customer_id" cascade="save-update">
</many-to-one>
</class>
</hibernate-mapping>

存在一对多的关系,想要在在获取一方的时候将关联的多方缓存起来,需要在集合属性下添加子标签,这里需要将关联的对象的hbm文件中必须在存在标签下也添加标签,不然Hibernate只会缓存OID。

<hibernate-mapping>
<class name="com.lippi.hibernate.pojos.Customer" table="customer">
<!-- 主键设置-->
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>
<!-- 属性设置-->
<property name="username" column="username" type="string"></property>
<property name="balance" column="balance" type="integer"></property>
<set name="orders" inverse="true" cascade="all" lazy="false" fetch="join">
<cache usage="read-only"/>
<key column="customer_id" ></key>
<one-to-many class="com.lippi.hibernate.pojos.Order"/>
</set>
</class>
</hibernate-mapping>

(5)在hibernate.cfg.xml中配置ehcache.xml文件的位置

<property name="cache.provider_configuration_file_resource_path">config/hibernate/ehcache/ehcache.xml</property>

(6)和Spring集成

在Spring集成Hibernate配置中,添加如下属性:

<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.EhCacheRegionFactory</prop>
🐶 您的支持将鼓励我继续创作 🐶

热评文章