hibernate的一级缓存和二级缓存详解
hibernate为我们提供了一级缓存和二级缓存,目的是为了减少应用程序对数据库的访问次数。
一级缓存:
(1)所谓一级缓存就是session级别的缓存,当我们使用他的范围是当前的session,当session关闭后,缓存也就不存在了。
(2)当调用save/saveOrUpdate/get/load/list/interator方法的时候,都会把对象存在session的缓存中
(3)一级缓存是由hibernate进行维护的,用户如果想要去操作缓存,可以通过hibernate提供的evict/clear/flush方法
特点: 只在当前Session范围内有效,缓存不能对多个session共享,作用时间短,效果不是特别明显!在短时间内多次操作数据库,效果比较明显
缓存相关几个方法的作用:
session.flush(); 让一级缓存与数据库同步
sessuib.evict(obj); 清空一级缓存中指定对象
session.clear(); 清空一级缓存中缓存的所有对象
二级缓存:
(1)hibernate为我们提供的二级缓存可以跨多个session,即不同的session都可以访问缓存数据。
(2)hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架,如果用户想要使用二级缓存,只需要在hibernate.cfg.xml中配置就行了,不想用直接移除,不影响代码。
(3)可以在hibernate.properties中查看hibernate默认对二级缓存的配置,如下图所示:
配置二级缓存:
1.步骤:
1) 开启二级缓存
2)指定缓存框架
3)指定那些类加入二级缓存
4)测试二级缓存!
2.缓存的一些策略:
<class-cache usage="read-only"/> 放入二级缓存的对象,只读;
<class-cache usage="nonstrict-read-write"/> 非严格的读写
<class-cache usage="read-write"/> 读写; 放入二级缓存的对象可以读、写;
<class-cache usage="transactional"/> (基于事务的策略)
3.集合缓存
<collection-cache usage="read-write" collection="cn.edu.Dept.emps"/>
4.hibernate.cfg.xml实例
<!--****************** 【二级缓存配置】****************** --> <!-- a. 开启二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- b. 指定使用哪一个缓存框架(默认提供的) --> <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> <!-- 开启查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property> <!-- c. 指定哪一些类,需要加入二级缓存 --> <class-cache usage="read-write" class="cn.edu.Dept" /> <class-cache usage="read-only" class="cn.edu.Employee" /> <!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] --> <collection-cache usage="read-write" collection="cn.edu.Dept.emps" />
5.测试
public class App { private static SessionFactory sf; static { sf = new Configuration() .configure() .addClass(Dept.class) .addClass(Employee.class) // 测试时候使用 .buildSessionFactory(); } // 1. 测试二级缓存的使用 // 没有/有用 二级缓存 @Test public void testCache() { Session session1 = sf.openSession(); session1.beginTransaction(); // a. 查询一次 Dept dept = (Dept) session1.get(Dept.class, 10); dept.getEmps().size();// 集合 session1.getTransaction().commit(); session1.close(); System.out.println("------"); // 第二个session Session session2 = sf.openSession(); session2.beginTransaction(); // a. 查询一次 dept = (Dept) session2.get(Dept.class, 10); // 二级缓存配置好; 这里不查询数据库 dept.getEmps().size(); session2.getTransaction().commit(); session2.close(); } @Test public void listCache() { Session session1 = sf.openSession(); session1.beginTransaction(); // HQL查询 【setCacheable 指定从二级缓存找,或者是放入二级缓存】 Query q = session1.createQuery("from Dept").setCacheable(true); System.out.println(q.list()); session1.getTransaction().commit(); session1.close(); Session session2 = sf.openSession(); session2.beginTransaction(); q = session2.createQuery("from Dept").setCacheable(true); System.out.println(q.list()); // 不查询数据库: 需要开启查询缓存 session2.getTransaction().commit(); session2.close(); } }