前言:使用缓存,是需要对应用系统进行性能优化而常采用的一种重要手段。合理地运用缓存,可以极大的提高应用系统的运行效率。
Hibernate中应用缓存:因为应用程序访问数据库,读写数据的代价非常高,而利用持久层的缓存可以减少应用程序与数据库之间的交互,即把访问过的数据保存到缓存中,应用程序再次访问已经访问过的数据,这些数据就可以从缓存中获取,而不必再从数据库中获取。同时如果数据库中的数据被修改或者删除,那么是、该数据所对应的缓存数据,也会被同步修改或删除,进而保持缓存数据的一致性。
Hibernate的二级缓存由SessionFactory对象管理,是应用级别的缓存。它可以缓存整个应用的持久化对象,所以又称为“SessionFactory缓存”。
hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据;否则查询数据库。
项目结构:
第一步:首先为Spring集成的Hibernate配置二级缓存,在beans.xml中加入如下配置:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xmlns:aop="http://www.springframework.org/schema/aop" 6 xmlns:tx="http://www.springframework.org/schema/tx" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 9 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 10 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 11 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> 12 13 <!-- <context:property-placeholder location="classpath:jdbc.properties"/> --> 14 <context:annotation-config/> 15 <!-- 配置dataSource --> 16 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 17 <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> 18 <property name="url" value="jdbc:oracle:thin:@192.168.1.10:1521:orcl"/> 19 <property name="username" value="tsrescue"/> 20 <property name="password" value="123456"/> 21 <!-- 连接池启动时的初始值 --> 22 <property name="initialSize" value="1"/> 23 <!-- 连接池的最大值 --> 24 <property name="maxActive" value="500"/> 25 <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> 26 <property name="maxIdle" value="2"/> 27 <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> 28 <property name="minIdle" value="1"/> 29 </bean> 30 <!-- 配置sessionFactory --> 31 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 32 <property name="dataSource" ref="dataSource"/> 33 <property name="mappingResources"> 34 <list> 35 <value>cn/itcast/bean/Person.hbm.xml</value> 36 </list> 37 </property> 38 <property name="hibernateProperties"> 39 <props> 40 <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> 41 <prop key="hibernate.show_sql">true</prop> 42 <prop key="hibernate.format_sql">true</prop> 43 <prop key="hibernate.cache.use_second_level_cache">true</prop><!-- 是否启用hibernate的二级缓存 --> 44 <prop key="hibernate.cache.use_query_cache">false</prop><!-- 是否启用查询缓存 --> 45 <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop><!-- 使用缓存产品的驱动类,这边提供的是hibernate的驱动类EhCache --> 46 </props> 47 48 </property> 49 </bean> 50 <!-- spring提供的针对hibernate的事务管理器 --> 51 <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 52 <property name="sessionFactory" ref="sessionFactory"/> 53 </bean> 54 <!-- 基于注解的方式声明事务 --> 55 <tx:annotation-driven transaction-manager="txManager"/> 56 <bean id = "personService" class="cn.itcast.Service.Impl.PersonServiceBean"/> 57 <bean name = "/person/list" class="cn.itcast.web.action.PersonAction"/> 58 </beans>
第二步:需要引入EhCachejar包 还要配置EhCache的配置文件ehcach.xml
ehcach.xml:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 3 defaultCache节点为缺省的缓存策略 4 maxElementsInMemory 内存中最大允许存在的对象数量 5 eternal 设置缓存中的对象是否永远不过期 6 overflowToDisk 把溢出的对象存放到硬盘上 7 timeToIdleSeconds 指定缓存对象空闲多长时间就过期,过期的对象会被清除掉 8 timeToLiveSeconds 指定缓存对象总的存活时间 9 diskPersistent 当jvm结束是是否持久化对象 10 diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间 11 --> 12 <ehcache> 13 <diskStore path="D:cache"/> 14 <defaultCache maxElementsInMemory="1000" 15 eternal="false"overflowToDisk="true" 16 timeToIdleSeconds="120" 17 timeToLiveSeconds="180" 18 diskPersistent="false" 19 diskExpiryThreadIntervalSeconds="60"/> 20 <cache name="cn.itcast.bean.Person" 21 maxElementsInMemory="100" <!-- 内存中最大允许存在的对象数量 --> 22 eternal="false" <!-- 设置缓存中的对象是否永远不过期 --> 23 overflowToDisk="true" <!-- 把溢出的对象存放到硬盘上 --> 24 timeToIdleSeconds="300" <!-- 指定缓存对象空闲多长时间就过期,过期的对象会被清除掉 --> 25 timeToLiveSeconds="600" <!-- 指定缓存对象总的存活时间 --> 26 diskPersistent="false"/><!-- 当jvm结束是是否持久化对象 --> 27 </ehcache>
第三步:测试一下
我们使用getPerson()获取数据库,然后关闭数据库,再使用getPerson()查询,如果查到,说明缓存成功。
1 @Test 2 public void testGetPerson() { 3 Person p = ps.getPerson(25); 4 System.out.println(p.getName()); 5 try { 6 System.out.println("请关闭数据库"); 7 Thread.sleep(1000*15); 8 } catch (InterruptedException e) { 9 e.printStackTrace(); 10 } 11 p = ps.getPerson(25); 12 System.out.println(p.getName()); 13 }