前面咱们已经讲解过了一级缓存,一级缓存也就是Session缓存,只在Session的范围内有效…做用时间就在Session的做用域中,范围比较小java
Hibernate为咱们提供了二级缓存功能:二级缓存是基于应用程序的缓存,全部的Session均可以使用数据库
Hibernate二级缓存:存储的是经常使用的类缓存
既然二级缓存是Hibernate自带的,那么咱们能够在hibernate.properties文件中找到对应的信息..markdown
经过配置文件咱们能够发现,二级缓存默认是不开启的,须要咱们手动开启,如下步骤:session
在hibernate.cfg.xml文件中开启二级缓存框架
<!-- a. 开启二级缓存 --> <property name="hibernate.cache.use_second_level_cache">true</property>
指定Hibernate自带的二级缓存框架就行了ide
<!-- b. 指定使用哪个缓存框架(默认提供的) --> <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- c. 指定哪一些类,须要加入二级缓存 --> <class-cache usage="read-write" class="zhongfucheng.aa.Monkey"/> <class-cache usage="read-only" class="zhongfucheng.aa.Cat"/>
咱们知道一级缓存是Session的缓存,那么咱们在测试二级缓存的时候使用两个Session来测试就行了。若是第二个Session拿到的是缓存数据,那么就证实二级缓存是有用的。测试
package zhongfucheng.aa; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.classic.Session; public class App5 { public static void main(String[] args) { //获取加载配置管理类 Configuration configuration = new Configuration(); //加载类对应的映射文件! configuration.configure().addClass(Animal.class); //建立Session工厂对象 SessionFactory factory = configuration.buildSessionFactory(); //获得Session对象 Session session1 = factory.openSession(); //使用Hibernate操做数据库,都要开启事务,获得事务对象 Transaction transaction = session1.getTransaction(); //开启事务 transaction.begin(); Monkey monkey = (Monkey) session1.get(Monkey.class,"40283f815be67f42015be67f43240001" ); System.out.println(monkey.getName()); System.out.println("-----------------------"); Session session2 = factory.openSession(); Transaction transaction2 = session2.getTransaction(); transaction2.begin(); Monkey monkey2 = (Monkey) session1.get(Monkey.class, "40283f815be67f42015be67f43240001"); System.out.println(monkey2.getName()); //提交事务 transaction.commit(); transaction2.commit(); //关闭Session session1.close(); session2.close(); } }
获得的是缓存数据!ui
咱们在把Animal类放进二级缓存的时候,用法为只读spa
也就是说,只能读取,不能写入,咱们来看看写入会怎么样:
monkey2.setName("小猴子");
抛出了异常….
usage的属性有4种:
若是咱们在数据库查询的数据是集合…Hibernate默认是没有为集合数据设置二级缓存的…所以仍是须要去读写数据库的信息
接下来,咱们就看看把集合设置为二级缓存是什么作的:
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] --> <collection-cache usage="read-write" collection="cn.itcast.b_second_cache.Dept.emps"/>
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(); }
list()和iterator()会把数据放在一级缓存,但一级缓存只在Session的做用域中有效…若是想要跨Session来使用,就要设置查询缓存
咱们在配置文件中还看到了查询缓存这么一条配置..
#hibernate.cache.use_query_cache true 【开启查询缓存】
也就是说,默认的查询数据是不放在二级缓存中的,若是咱们想要把查询出来的数据放到二级缓存,就须要在配置文件中开启
<!-- 开启查询缓存 --> <property name="hibernate.cache.use_query_cache">true</property>
@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(); }