一级缓存解决在一次查询中,只与数据库交互一次
二级缓存解决一些常用的、公开的数据存放起来,方便使用,那查询缓存呢?
一、查询缓存的原理
一级缓存和二级缓存都是对象的缓存。对象缓存就是把该对象对应的数据库表中的所有的字段全部查询出来,而这种查询通常会让小效率降低,比如,表中字段很多,但程序中只需要几个字段,而这样的情况,使用一级缓存或二级缓存会让效率降低。
查询缓存也叫数据缓存,也就是说内存中需要多少数据,就把多少数据放入到查询缓存,这样就大大提高了查询效率。所以查询缓存解决了一张表中部分字段查询的问题。
1.1 生命周期
只要数据放入到查询缓存中,该缓存会一直存在,直到缓存中的数据被修改了,该缓存的生命周期结束.
两者构成了查询缓存。
1.2 操作
1.3 思考:
Hibernate是如判断查询缓存中的值与数据库中的值是否一样呢?
一样就保存,不一样就干掉。实际上 Hibernate 利用的时间戳缓存来判断数据的有效性,时间戳中记录了查询缓存从创建到清除的变化日志,Hibernate 利用该日志来判断缓存中的数据是否更新
二、查询缓存的应用
1.开启二级缓存
public class QueryCacheTest { private Session session; private Transaction transaction; private SessionFactory sessionFactory; @Test public void testList1(){ session = HibernateUtils.openSession(); Query query = session.createQuery("from Classes"); query.setCacheable(true);//query要使用查询缓存 query.list();//把数据放入查询缓存 session.close(); session = HibernateUtils.openSession(); query = session.createQuery("from Classes"); query.setCacheable(true); query.list();//不发出sql session.close(); } /** * "select name from Classes" 查name * 查询出来的数据能够放入到查询缓存中 * 但是不能放入到二级缓存中,因为不是对象 */ @Test public void testList_2(){ session = HibernateUtils.openSession(); Query query = session.createQuery("select name from Classes"); query.setCacheable(true); query.list(); System.out.println(HibernateUtils.getSessionFactory() .getStatistics().getEntityLoadCount());//0,因为name就是一个数据,不是对象,所以不能放到二级缓存中 session.close(); session = HibernateUtils.openSession(); query = session.createQuery("select name from Classes"); query.setCacheable(true); query.list(); session.close(); } /** * 如果两个hql一样,则可以利用查询缓存, * 如果不一样,哪怕有一点不一样,就不能够利用了。 */ @Test public void testList_3(){ session = HibernateUtils.openSession(); Query query = session.createQuery("select name from Classes"); query.setCacheable(true); query.list(); session.close(); session = HibernateUtils.openSession(); query = session.createQuery("select name from Classes where cid=1"); query.setCacheable(true); query.list();//发出sql语句,按理说第二条hql可以从第一条中取,但是查询缓存不行,其命中率特别低 session.close(); } /** * 先把一些数据放入到查询缓存中,修改一些数据,看生命周期 */ @Test public void testActiveTime(){ /** * 把name放入到了查询缓存中 */ Session session = HibernateUtils.openSession(); Query query = session.createQuery("select name from Classes"); query.setCacheable(true); query.list(); session.close(); /** * 修改name属性的值 * 修改了查询缓存的时间戳缓存,从而知道了该数据已经被修改了,查询缓存中的数据就被清空了 */ session = HibernateUtils.openSession(); transaction = session.beginTransaction(); Classes classes = (Classes)session.get(Classes.class, 1L); classes.setName("123213456"); transaction.commit(); session.close(); /** * 再次查询name属性的值,查询缓存中name属性的值清空了 */ session = HibernateUtils.openSession(); query = session.createQuery("select name from Classes"); query.setCacheable(true); query.list();//发出sql session.close(); } }