您的位置:首页 > 编程语言 > Java开发

在Spring+Hibernate集成环境中使用EhCache缓存

2017-10-18 12:35 387 查看
 #缓存的配置

在applicationContext.xml加入使用缓存的属性

<!--启动查询缓存 -->
<prop key="hibernate.cache.use_query_cache">true</prop>
<!--设置缓存机制为二级缓存 -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<!--设置二级缓存的Provider类 -->
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<!--设置缓存的配置文件路径 -->
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>

整体的applicationContext.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
<!-- 引用外部文件 db.properties读取数据库配置-->
<context:property-placeholder location="classpath:db.properties"/>

<!-- schemaLocation后面两个命名空间是扫描该包必须有的 -->
<!-- 扫描com.sunline包以及所有子包,为所有加了注解的类创建bean -->
<context:component-scan base-package="com.sunline">
</context:component-scan>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="${driverClassName}">
</property>
<property name="url"
value="${url}">
</property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<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.MySQLDialect
</prop>
<prop key="dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">true</prop>
<prop key="hibernate.show_sql">true</prop>

<!--启动查询缓存 -->
<prop key="hibernate.cache.use_query_cache">true</prop>
<!--设置缓存机制为二级缓存 -->
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<!--设置二级缓存的Provider类 -->
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<!--设置缓存的配置文件路径 -->
<prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>com/sunline/entity/User.hbm.xml</value>
</list>
</property>
</bean>

<!-- 配置Hibernate事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

  完成ehcache.xml的配置

<ehcache>
<diskStore path="d:/ehcache"/>
<!-- diskStore path="d:/ehcache"/               path="java.io.tmpdir"
缓存存储路径
-->

<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>

<cache name="Cache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>

<!-- 使用Ehcache查询缓存,需要配置以下两项 -->
<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"
/>
</ehcache>

在数据模型层User.hbm.xml映射文件Cache配置的class节点下,加入类似如下格式信息

<class name="com.sunline.entity.User" table="user" catalog="association">
<cache usage="read-write" region="Cache"/>

#数据模型层

package com.sunline.entity;

/**
* User entity. @author MyEclipse Persistence Tools
*/

public class User  implements java.io.Serializable {

// Fields

private Integer id;
private String userName;
private String userPassword;
private String userInfo;

// Constructors

/** default constructor */
public User() {
}

/** full constructor */
public User(String userName, String userPassword, String userInfo) {
this.userName = userName;
this.userPassword = userPassword;
this.userInfo = userInfo;
}

// Property accessors

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUserName() {
return this.userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getUserPassword() {
return this.userPassword;
}

public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}

public String getUserInfo() {
return this.userInfo;
}

public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
}

<?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">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.sunline.entity.User" table="user" catalog="association">
<cache usage="read-write" region="Cache"/>
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="increment"></generator>
</id>
<property name="userName" type="java.lang.String">
<column name="user_name" length="200" not-null="true" />
</property>
<property name="userPassword" type="java.lang.String">
<column name="user_password" length="50" not-null="true" />
</property>
<property name="userInfo" type="java.lang.String">
<column name="user_info" length="60" not-null="true" />
</property>
</class>
</hibernate-mapping>

#数据访问层

package com.sunline.dao;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;

import com.sunline.entity.User;

@Repository(value="userDao")
public class UserDao extends HibernateDaoSupport {

/*
* 使用注解必须添加以下方式
*/
@Resource
public void setSessionFacotry(SessionFactory sessionFacotry) {
super.setSessionFactory(sessionFacotry);
}

/*
* 查找所有用户
*/
@SuppressWarnings("unchecked")
public List<User> findAll(){
String sql="from User";
getHibernateTemplate().setCacheQueries(true);
getHibernateTemplate().setQueryCacheRegion(sql);               //这行可省略
List<User> list=this.getHibernateTemplate().find(sql);
getHibernateTemplate().setCacheQueries(false);                //避免出现N+1情况
return list;
}

}

#业务逻辑层

package com.sunline.biz;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.sunline.dao.UserDao;
import com.sunline.entity.User;

@Service(value="userBiz")
public class UserBiz {

@Autowired
@Qualifier("userDao")            //使用@Qualifier注解来说明使用哪一个实现类
UserDao userDao;

/*
* 查找所有用户
*/
public List<User> findAll(){
return userDao.findAll();
}

}

#测试类

package com.sunline.test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.sunline.biz.UserBiz;
import com.sunline.entity.User;

@Transactional(propagation=Propagation.REQUIRED)
public class Test {

/**
* @param args
*/
@Transactional(propagation=Propagation.REQUIRED)        //用事务管理做双重保障
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserBiz userBiz = (UserBiz) ctx.getBean("userBiz");

System.out.println("第一次开始获取");        //获取数据库中的数据
List<User> list = userBiz.findAll();
for(User user : list){
System.out.println("你的个人信息为: "+user.getUserName()+" "+user.getUserPassword()+" "+user.getUserInfo());
}

try {
System.out.println("请关闭数据库");
Thread.sleep(1000*40);              //线程休眠40秒,手动关闭数据库服务.测试缓存数据
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("第二次开始获取");         //获取的是缓存数据
List<User> list2 = userBiz.findAll();
for(User user : list2){
System.out.println("你的个人信息为: "+user.getUserName()+" "+user.getUserPassword()+" "+user.getUserInfo());
}
}

}

#结果:

1.缓存保存在D:\ehcache下,运行后出现

             


2.运行结果:



#总结:

发现在线程休眠,手动关闭数据库服务后,仍能读取出数据,说明读取的是缓存的数据,并非数据库中的数据.

#注意:

      使用ehcache,打印sql语句是正常的,因为query cache设置为true将会创建两个缓存区域:一个用于保存查询结果集 (org.hibernate.cache.StandardQueryCache); 另一个则用于保存最近查询的一系列表的时间戳(org.hibernate.cache.UpdateTimestampsCache)。请注意:在查询缓存中,它并不缓存结果集中所包含的实体的确切状态;它只缓存这些实体的标识符属性的值、以及各值类型的结果。需要将打印sql语句与最近的cache内
容相比较,将不同之处修改到cache中,所以查询缓存通常会和二级缓存一起使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: