网上有很多关于spring+hibernate 二级缓存的配置文章,但是java使用实例不是很多,所以我把这两个加在一起来写一个文章,一个方便自己查阅,一方面希望能够给查资料的人们提供些许方便。
这里使用的环境:spring3.0+hibernate3.2+ehcache。相关环境配置和jar包引入略。
配置:
1、hibernate-mapping.xml配置文件中添加:
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
2、Hibernate允许在类和集合的粒度上设置第二级缓存。在映射文件中,<class>和<set>元素都有一个<cache>子元素,这个子元素用来配置二级缓存。
示例:以category(产品类别)和product(产品)的映射为例:
修改要配置缓存的那个持久化类的对象关系映射文件:
Category.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.qiujy.domain.cachedemo.Category" table="categories">
<!—
配置缓存,必须紧跟在class元素后面
对缓存中的Category对象采用读写型的并发访问策略
-->
<cache usage="read-write"/>
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="native" />
</id>
<!-- 配置版本号,必须紧跟在id元素后面 -->
<version name="version" column="version" type="java.lang.Long" />
<property name="name" type="java.lang.String">
<column name="name" length="32" not-null="true"/>
</property>
<property name="description" type="java.lang.String">
<column name="description" length="255"/>
</property>
<set name="products" table="products" cascade="all" inverse="true">
<!-- Hibernate只会缓存对象的简单属性的值,
要缓存集合属性,必须在集合元素中也加入<cache>子元素
而Hibernate仅仅是把与当前持久对象关联的对象的OID存放到缓存中。
如果希望把整个关联的对象的所有数据都存入缓存,
则要在相应关联的对象的映射文件中配置<cache>元素
-->
<cache usage="read-write"/>
<key column="categoryId" not-null="true"/>
<one-to-many class="org.qiujy.domain.cachedemo.Product"/>
</set>
</class>
</hibernate-mapping>
Product.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.qiujy.domain.cachedemo.Product" table="products">
<cache usage="read-write"/>
<id name="id" type="java.lang.Long">
<column name="id" />
<generator class="native" />
</id>
<!-- 配置版本号,必须紧跟在id元素后面 -->
<version name="version" column="version" type="java.lang.Long" />
<property name="name" type="java.lang.String">
<column name="name" length="32" not-null="true"/>
</property>
<property name="description" type="java.lang.String">
<column name="description" length="255"/>
</property>
<property name="unitCost" type="java.lang.Double">
<column name="unitCost" />
</property>
<property name="pubTime" type="java.util.Date">
<column name="pubTime" not-null="true" />
</property>
<many-to-one name="category"
column="categoryId"
class="org.qiujy.domain.cachedemo.Category"
cascade="save-update"
not-null="true">
</many-to-one>
</class>
</hibernate-mapping>
3、编辑ehcache.xml文件:
<ehcache>
<diskStore path="c:\\ehcache\"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!-- 设置Category类的缓存的数据过期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category"
maxElementsInMemory="100"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
<!-- 设置Category类的products集合的缓存的数据过期策略 -->
<cache name="org.qiujy.domain.cachedemo.Category.products"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="org.qiujy.domain.cachedemo.Product"
maxElementsInMemory="500"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="workUnitHisCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="2400"
timeToLiveSeconds="2400"
overflowToDisk="false"/>
</ehcache>
到此基本配置文件完成了。
使用:(以workUnitHisCache为例,上面两个是为了说明多对一关系的配置,最后一个的hbm.xml文件没有贴出来,知道怎么配置就可以了)
代码:
@Service
public class WorkUnitHisServiceImpl {
private static final Logger log = LoggerFactory.getLogger(WorkUnitHisServiceImpl.class);
@Autowired
private ITestdao testdao;
@Autowired //spring注解方式注入cache
private Cache workUnitHisCache;
private Boolean useCache = true;
@SuppressWarnings("unchecked")
@Override
public PageResult<Test> test(
String condition) {
//在缓存中取值(如果缓存中没有值,则从数据库中取值)
PageResultVO<WorkUnitHisCount> pageCache = null;
if (this.useCache) { //是否使用cache
if (log.isDebugEnabled()) {
log.debug("WorkUnitHisCount缓存开启,从缓存中获取WorkUnitHisCount,typeCode:" + "");
}
//在缓存中取值,get()参数为放入缓存中的key
Element element = this.workUnitHisCache.get(condition);
if (element != null && element.getObjectValue() != null) {
//缓存中放入什么,则此处可以取出什么
pageCache = (PageResultVO<WorkUnitHisCount>)element.getObjectValue();
}
}
if (pageCache == null) { //如果该对象为null,则缓存中没有对象,需要从数据库中取数据并放入到缓存中
if (log.isDebugEnabled()) {
log.debug("从数据库中获取WorkUnitHisCount,typeCode:" + "" );
}
//在数据库中取值
pageCache = testdao.testget(condition);
//将结果放入到缓存中
if (this.useCache) {
Element element = new Element(condition, pageCache);
this.workUnitHisCache.put(element);
}
}
return pageCache;
}
}
其中:
@Autowired
private Cache workUnitHisCache;
如果不采用注解的方式,java类中增加get、set方法,spring配置文件中如下配置:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- ================================================ -->
<!-- echcache extention config -->
<!-- ================================================ -->
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean >
<bean id ="workUnitHisCache" class ="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager" />
<property name="cacheName" value="workUnitHisCache" />
</bean>
</beans>
到此结束了。欢迎高手指点,有问题者及时提问。