1. 引入 EHCache 相关的 JAR 包
读者可以从官方网址 http://www.ehcache.org/downloads/ 中下载 EHCache 的 JAR 包,成功访问后的页面显示如图 1 所示。图 1 EHCache的下载
从图 1 中可以看出,目前 EHCache 的最新版本为 ehcache-3.7,本教程使用的是 ehcache-2.10.5,单击图中 Ehcache 2.x 下方的链接,即可下载此版本的 EHCache。下载并解压后,在压缩包文件中找到 ehcache-2.10.5.jar,将其复制到 hibernateDemo05 项目的 lib 目录中,并发布到类路径下即可。
2. 引入 EHCache 的配置文件 ehcache.xml
读者可以直接从 Hibernate 的解压包的 hibernate-distribution-3.6.10.Final\project\etc 目录中找到 ehcache.xml,找到后,将此文件复制到项目的 src 目录下。ehcache.xml 文件中的主要代码如下所示:<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false"> <diskStore path="java.io.tmpdir/Tmp_EhCache" /> <defaultCache eternal="false" maxElementsInMemory="10000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="259200" memoryStoreEvictionPolicy="LRU" /> <cache name="cloud_user" eternal="false" maxElementsInMemory="5000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" memoryStoreEvictionPolicy="LRU" /> </ehcache>在上述配置代码中,各个元素作用如下表所示:
名称 | 说明 |
---|---|
<diskStore>元素 | 用于设置缓存数据文件的存储目录 |
<defaultCache>元素 | 用于设置缓存的默认数据过期策略。 |
<cache>元素 | 用于设置具体的命名缓存的数据过期策略。 |
maxElementsInMemory 属性 | 用于设置缓存对象的最大数目 |
eternal 属性 | 用于指定是否永不过期,true 为不过期,false 为过期。 |
timeToIdleSeconds 属性 | 用于设置对象处于空闲状态的最大秒数。 |
timeToLiveSeconds 属性 | 用于设置对象处于缓存状态的最大秒数。 |
overflowToDisk 属性 | 用于设置内存溢出时是否将溢出对象写入硬盘。 |
3. 启用二级缓存
在 Hibernate 的核心配置文件中启用二级缓存,并指定哪些实体类需要存储到二级缓存中。其配置代码如下所示:<property name ="hibernate.cache.use_second_level_cache">true </property> <property name ="hibernate.cache.provider_class"> org.hibernate.cache.EhCacheProvider </property > <mapping resource ="com/mengma/domain/Person.hbm.xml"/> <class-cache usage ="read-write" class ="com.mengma.domain.Person"/>在上述配置代码中,hibernate.cache.use_second_level_cache 用于开启二级缓存,hibernate.cache.provider_class 用于指定二级缓存的供应商。
<class-cache> 标签用于指定将哪些数据存储到二级缓存中,其中 usage 属性表示指定缓存策略。需要注意的是,<class-cache> 标签必须放在 <mapping> 标签的后面。
4. 创建测试类
在 com.mengma.test 包下创建一个名为 SecondEHChcheTest 的测试类,并在类中添加一个 testCache() 方法。在 testCache() 方法中,需要开启两个 Session 对象,然后使用 get() 方法查询四次,通过比较查询结果,观察二级缓存的使用情况。其实现代码如下所示。package com.mengma.test; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.mengma.domain.Person; import com.mengma.utils.HibernateUtils; public class SecondEHChcheTest { @Test public void testCache() { Session session1 = HibernateUtils.getSession(); // 开启第一个Session对象 Transaction tx1 = session1.beginTransaction(); // 开启第一个事务 Person p1 = (Person) session1.get(Person.class, 1); // 获取p1对象 Person p2 = (Person) session1.get(Person.class, 1); // 获取p2对象 System.out.println(p1 == p2); // 第一次比较 tx1.commit(); // 提交事务 session1.close(); // sesison1对象关闭,一级缓存被清理 Session session2 = HibernateUtils.getSession(); // 开启第二个Session对象 Transaction tx2 = session2.beginTransaction();// 开启第二个事务 Person p3 = (Person) session2.get(Person.class, 1); // 获取p3对象 System.out.println(p1 == p3); // 第二次比较 Person p4 = (Person) session2.get(Person.class, 1); // 获取p4对象 System.out.println(p3 == p4); // 第三次比较 tx2.commit(); // 提交事务2 session2.close(); // session2关闭 } }
5. 运行程序并查看结果
使用 JUnit 测试运行 testCache() 方法,运行成功后,控制台的输出结果如图 2 所示。图 2 testCache() 方法的测试结果
从图 2 中可以看到,控制台只输出了一个查询 SQL,这说明 Hibernate 只在数据库中查询了一次。而下面的 true、false 和 true 是三次比较输出的结果。详细解释具体如下。
1)在上述代码中,开启了两个 Session 和事务,从第一个 Session 中获取 p1 对象时,由于一级缓存和二级缓存中没有相应的数据,需要从数据库中查询,所以发出了 SQL 语句。
2)查询出 p1 对象后,p1 对象会保存到一级缓存和二级缓存中。当获取 p2 对象时,因为 Session 没有关闭,所以会从一级缓存中取出该对象。由于 p1 和 p2 对象都保存在一级缓存中,而且指向的是同一实体对象,所以第一次输出结果为true。
3)接着提交事务 tx1,并关闭 session1,此时一级缓存中的数据会被清除。
4)接下来开启第二个 Session 和事务,获取 p3 对象,此时控制台没有产生 SQL 语句是因为 p3 对象是从二级缓存中获取的。取出后,二级缓存会将数据同步到一级缓存中,这时 p3 对象又在一级缓存中存在了。
5)因为 p3 对象是从二级缓存中获取的,而二级缓存中存储的都是对象的散装数据,它们会重新 new 出一个新的对象,所以第二次输出的结果为 false。
6)最后获取 p4 对象时,由于一级缓存中已经存在了 Person 对象,Hibernate 会直接从一级缓存中获取,所以输出结果为 true。