Hibernate使用二级缓存,Hibernate本身没有实现二级缓存,所以我们都是使用的第三方的缓存,这里只是介绍使用Ehcache缓存
使用步骤:
1、引用jar包
2、引用配置文件ehcache.xml
<!--ehcache二级缓存的配置信息-->
<ehcache>
<!-- 如果二级缓存的数量超出的存储的磁盘路径 -->
<diskStore path="G:/cache"/>
<!--
默认的配置
maxInMemory -设置内存存储的最大数量
eternal -设置二级缓存中缓存对象的是否永久有效,一般都是false
timeToIdleSeconds -空闲时间,设置缓存对象的最大空闲时间,单位秒
timeToLiveSeconds -生命周期,设置对象的存活时间,超出更新缓存内容
overflowToDisk -如果缓存对象的数量超出设置的内存最大数量,将超出存储到磁盘
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--Predefined caches. Add your cache configuration settings here.
If you do not have a configuration for your cache a WARNING will be issued when the
CacheManager starts
The following attributes are required for defaultCache:
name - Sets the name of the cache. This is used to identify the cache. It must be unique.
maxInMemory - Sets the maximum number of objects that will be created in memory
eternal - Sets whether elements are eternal. If eternal, timeouts are ignored and the element
is never expired.
timeToIdleSeconds - Sets the time to idle for an element beforeQuery it expires. Is only used
if the element is not eternal. Idle time is now - last accessed time
timeToLiveSeconds - Sets the time to live for an element beforeQuery it expires. Is only used
if the element is not eternal. TTL is now - creation time
overflowToDisk - Sets whether elements can overflow to disk when the in-memory cache
has reached the maxInMemory limit.
-->
<!-- Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.
If there are more than 10000 elements it will overflow to the
disk cache, which in this configuration will go to wherever java.io.tmp is
defined on your system. On a standard Linux system this will be /tmp"
-->
<cache name="sampleCache1"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<!-- Sample cache named sampleCache2
This cache contains 1000 elements. Elements will always be held in memory.
They are not expired. -->
<cache name="sampleCache2"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/> -->
<!-- Place configuration for your caches following -->
</ehcache>
``
3、在hibernate.cfg.xml中启用二级缓存并配置
true
org.hibernate.cache.ehcache.EhCacheRegionFactory
true
4、在类的mapping文件中添加二级缓存的使用
注意:cache标签只能出现在class的下面和id的上面
5、测试就可以了
oid操作基本上都会操作二级缓存
而HQL操作默认不会操作二级缓存,想要操作需要开启查询缓存
query.setCacheable(true)
测试代码:
//缓存
public class MyTest {
private Session session;
private Transaction tran;
// 每次执行单元测试的时候,都会优先执行
@Before
public void bre() {
session = HibUtils.getSession();
tran = session.beginTransaction();
}
// 验证一级缓存的存在
@Test
public void test1() {
// 会发起SQL
Cource cource = session.get(Cource.class, 1);
// 不会发起SQL
Cource cource3 = session.get(Cource.class, 1);
session.evict(cource);// 移除
// 再次发起SQL语句
Cource cource2 = session.get(Cource.class, 1);
Session session2 = HibUtils.openSession();
System.out.println("第一个:" + session.hashCode());
System.out.println("第二个:" + session2.hashCode());
// 创建另外的Session
Cource cource4 = session2.get(Cource.class, 1);
}
// 二级缓存:存储在SessionFactory
// oid操作会存储到二级缓存中
@Test
public void test2() {
Session session1 = HibUtils.openSession();
Session session2 = HibUtils.openSession();
System.out.println("1:" + session1.hashCode());
System.out.println("2:" + session2.hashCode());
Cource cource1 = session1.get(Cource.class, 1);
// 不会发起SQL语句,因为有二级缓存
Cource cource2 = session2.get(Cource.class, 1);
SessionFactory factory = HibUtils.getFactory();
System.out.println(factory.getStatistics().getSecondLevelCachePutCount());
}
// HQL\SQL\QBC会不会跟二级缓存
@Test
public void test3() {
String hql = "from Cource ";
Session session1 = HibUtils.openSession();
Session session2 = HibUtils.openSession();
// 不使用查询缓存
Query<Cource> query1 = session1.createQuery(hql);
Cource cource1 = query1.getSingleResult();//
Query<Cource> query2 = session1.createQuery(hql);
Cource cource2 = query2.getSingleResult();
System.out.println(cource1 == cource2);// true
// 开启2次sql查询
// 无论是否使用查询缓存当查询结果返回时都会经过一级缓存,这时如果存在那么就不会新建对象
// 使用查询缓存---使用二级缓存
Query<Cource> query3 = session1.createQuery(hql);
query3.setCacheable(true);
Cource cource3 = query3.getSingleResult();
Query<Cource> query4 = session2.createQuery(hql);
query4.setCacheable(true);
Cource cource4 = query4.getSingleResult();
System.out.println(cource3 == cource4);// false
// 开启一次SQL查询
// 因为查询需要检索二级缓存,重新创建对象
}
//演示查询结果的路径,是否走一级缓存或二级缓存
@Test
public void test4() {
String hql = "from Cource where id=1 ";
Session session1 = HibUtils.openSession();
Session session2 = HibUtils.openSession();
// 使用查询缓存---使用二级缓存
Query<Cource> query3 = session1.createQuery(hql);
query3.setCacheable(true);
Cource cource3 = query3.getSingleResult();
Query<Cource> query4 = session2.createQuery("from Cource");
query4.setCacheable(true);
List<Cource> list = query4.getResultList();
System.out.println("单个:id=1:"+cource3.hashCode());
System.out.println("第二次:id=1:" +list.get(0).getId()+"---->"+
list.get(0).hashCode());
}
// 每次只需单元测试的时候,都会最后执行
@After
public void aft() {
tran.commit();
}
}
“`
使用二级缓存要小心,对于频繁改变的数据和特别敏感的数据都不要使用二级缓存。