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>
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8