Hibernate旅程(九)Hibernate缓存机制--查询缓存
来源:互联网 发布:如何淘宝店铺装修 编辑:程序博客网 时间:2024/06/05 02:26
Hibernate查询缓存
我们介绍了Hibernate一级缓存,二级缓存。而hibernate二级缓存时针对Id查询的缓存策略,对于条件查询则毫无作用。因此hibernate提供了针对条件查询的QueryCache(查询策略)。
下面来看session控制的查询缓存。
一、查询缓存配置
1、 在hibernate.cfg.xml中加入查询缓存的策略,<propertyname="hibernate.cache.use_query_cache">true</property> 启用查询缓存的策略,默认是false。
二、关闭二级缓存,采用query.list()查询普通属性
代码如下所示。
public voidtestCache1() { Session session = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); Listnames = session.createQuery("select s.name from Student s") .setCacheable(true) .list(); for (int i=0;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } System.out.println("-------------------------------------------------------"); //不会发出查询语句,因为启用查询缓存 names= session.createQuery("select s.name from Student s") .setCacheable(true) .list(); for (int i=0;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
我们可以看到控制台输出语句,仅输出一次:Hibernate: select student0_.name as col_0_0_ fromt_student student0_
由此可知,我们开启了查询缓存,第一次进行查询的时候,已经把结果放到querycache中,当第二次再次做出相同的查询的时候,就不再向数据库发重复的sql语句了。
三、关闭二级缓存,启用查询缓存,采用query.list()查询普通属性
代码就如下所示。
public voidtestCache2() { Sessionsession = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); Listnames = session.createQuery("select s.name from Student s") .setCacheable(true) .list(); for (int i=0;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } System.out.println("-------------------------------------------------------"); try { session= HibernateUtils.getSession(); session.beginTransaction(); //不会发出查询语句,因为查询缓存和session的生命周期没有关系 Listnames = session.createQuery("select s.name from Student s") .setCacheable(true) .list(); for (int i=0;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
运行结果如下所示。
控制台打印结果:
select student0_.name as col_0_0_ fromt_student student0_
班级0的学生0
班级0的学生1
班级0的学生2
班级0的学生3
班级0的学生4
班级0的学生5…
我们可以看出,同样,只打印一次查询语句,如果没有开启查询缓存的话,并且关闭二级缓存的情况下,还会去数据库再查询一遍,而我们的程序中没有再去重复的去数据库中查询的原因是,当开启query缓存的时候,查询缓存的生命周期与session无关。
四、关闭二级缓存,开启查询,采用query.iterate()查询普通属性
代码如下所示。
public voidtestCache3() { Sessionsession = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); Iteratoriter = session.createQuery("select s.name from Student s") .setCacheable(true) .iterate(); while(iter.hasNext()){ Stringname = (String)iter.next(); System.out.println(name); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } System.out.println("-------------------------------------------------------"); try { session= HibernateUtils.getSession(); session.beginTransaction(); //会发出查询语句,query.iterate()查询普通属性它不会使用查询缓存 //查询缓存只对query.list()起作用 Iteratoriter = session.createQuery("select s.name from Student s") .setCacheable(true) .iterate(); while(iter.hasNext()){ Stringname = (String)iter.next(); System.out.println(name); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
显控制台显示结果打印了两次sql语句。
-------------------------------------------------------
Hibernate: select student0_.name as col_0_0_from t_student student0_
根据这样的结果我们发现,quer.iterate()查询普通属性它是不会使用查询缓存,查询缓存只对query.list()起作用。
五、关闭二级缓存,关闭查询缓存,采用query.list()查询实体
代码如下所示。
public voidtestCache4() { Sessionsession = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); List students =session.createQuery("select s from Student s") .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } System.out.println("-------------------------------------------------------"); try { session= HibernateUtils.getSession(); session.beginTransaction(); //会发出查询语句,默认query.list()每次执行都会发出查询语句 List students =session.createQuery("select s from Student s") .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
显示结果如下所示。
控制台上打印两次sql语句。
Hibernate:select student0_.id as id0_, student0_.name as name0_, student0_.classesid asclassesid0_ from t_student student0_
班级0的学生0
班级0的学生1
班级0的学生2
班级0的学生3
班级0的学生4
由此可知,不开启查询缓存,默认query.list每次执行都会发出查询语句。
六、关闭二级缓存,开启查询缓存,采用query.list()查询实体
代码如下所示。
Session session = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); Liststudents = session.createQuery("select s from Student s") .setCacheable(true) .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } System.out.println("-------------------------------------------------------"); try { session= HibernateUtils.getSession(); session.beginTransaction(); //会发出n条查询语句,因为开启了查询缓存,关闭了二级缓存,那么查询缓存就会缓存实体对象的id //第二次执行query.list(),将查询缓存中的id依次取出,分别到一级缓存和二级缓存中查询相应的实体 //对象,如果存在就使用缓存中的实体对象,否则根据id发出查询学生的语句 Liststudents = session.createQuery("select s from Student s") .setCacheable(true) .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); }
控制台打印sql如下图所示。
在第一次查询的时候,发出一条sql语句查询出结果,因为我们开启了查询缓存,会把第一次查询出的实体结果集的id放到查询缓存中,第二次再次执行query.list()的时候,会把id拿出来,到相应的缓存去找,因为是跨session,在二级缓存中找不到,所以每次都会发出查询语句,二级缓存中不存在,有多少个id就会发出查询语句多少次。
七、开启二级缓存,开启查询缓存,采用query.list()查询实体
代码如下所示。
/** * 开启查询,开启二级缓存,采用query.list()查询实体 * * 在两个session中发query.list()查询 */ public voidtestCache6() { Sessionsession = null; try { session= HibernateUtils.getSession(); session.beginTransaction(); Liststudents = session.createQuery("select s from Student s") .setCacheable(true) .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } System.out.println("-------------------------------------------------------"); try { session= HibernateUtils.getSession(); session.beginTransaction(); //不再发出查询语句,因为配置了二级缓存和查询缓存 Liststudents = session.createQuery("select s from Student s") .setCacheable(true) .list(); for (int i=0;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } }catch(Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); }finally { HibernateUtils.closeSession(session); } }
结果如下所示
Hibernate: select student0_.id as id0_,student0_.name as name0_, student0_.classesid as classesid0_ from t_studentstudent0_
只发出一次sql请求,当我们第一次执行query.list()会放到二级缓存中,和query缓存中。当我们第一次执行查询时,会找到相应的id到缓存中查找,在二级缓存中存在,则直接从二级缓存中取出数据,不再向数据库中发出sql语句。
八、查询缓存总结
查询缓存是缓存普通属性结果集的,对实体对象的结果集会缓存id。查询缓存的生命周期,当关联的表发生修改时,查询缓存的生命周期结束。
而开启缓存的时候,我们就要去维护缓存,如果缓存和内存中的数据不一致的话,和数据不同步,可能给用户显示的是脏数据了。所以根据需要使用缓存机制。
- Hibernate旅程(九)Hibernate缓存机制--查询缓存
- Hibernate旅程(七)Hibernate缓存机制--一级缓存
- Hibernate旅程(八)Hibernate缓存机制--二级缓存
- hibernate的查询缓存机制
- 【hibernate框架】缓存机制之查询缓存
- Hibernate 缓存机制续 - 查询缓存
- hibernate缓存机制(四)-查询缓存
- hibernate回顾之缓存机制-一级缓存、二级缓存、查询缓存
- hibernate回顾之缓存机制-一级缓存、二级缓存、查询缓存
- hibernate三级缓存(查询缓存)
- hibernate缓存机制(一)
- hibernate缓存机制(二)
- hibernate缓存机制(转载)
- hibernate缓存机制(二)
- hibernate缓存机制(三)
- 【Hibernate】(3)Hibernate的缓存机制
- Hibernate缓存☞查询缓存
- hibernate缓存之【查询缓存】
- MFC 串口编程详细教程 图文并茂
- 玩时间2
- MYSQL创建数据库时候直接指定编码和排序规则
- Android中的长度单位详解
- 解决重装 Oracle 出现的 INS-32025 问题,完全卸载 Oracle11g
- Hibernate旅程(九)Hibernate缓存机制--查询缓存
- Hive下的变量使用
- CSS常用属性
- ALSA(Advanced Linux Sound Architecture)声卡编程介绍
- 聊一聊,android程序员前景如何
- iframe的使用方法
- Java 使用 URLConnection 模拟 Http Get和Post 提交
- UIDevice 设备信息
- struts2 升级 2.3.15.1以后 (There is no Action mapped for namespace [/] and action)