hibernate查询缓存详细分析

 一、查询缓存配置

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查询缓存详细分析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 详解Java的Hibernate框架中的缓存与原生SQL语句的使用

    Hibernate缓存 缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现. 缓存对Hibernate很重要,它采用了多级缓存方案下文所述: 第一级缓存: 第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过. Session对象不断自身的动力的对象,提交到数据库之前. 如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量.如果您关闭会话,所有被缓

  • 详解Java的Hibernate框架中的注解与缓存

    注解 Hibernate注解是一个没有使用XML文件来定义映射的最新方法.可以在除或替换的XML映射元数据使用注解. Hibernate的注解是强大的方式来提供元数据对象和关系表的映射.所有的元数据被杵到一起的代码POJO java文件这可以帮助用户在开发过程中同时要了解表的结构和POJO. 如果打算让应用程序移植到其他EJB3规范的ORM应用程序,必须使用注解来表示映射信息,但仍然如果想要更大的灵活性,那么应该使用基于XML的映射去. 环境设置Hibernate注释 首先,必须确保使用的是JD

  • java模拟hibernate一级缓存示例分享

    纯Java代码模拟Hibernate一级缓存原理,简单易懂. 复制代码 代码如下: import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map; public class LevelOneCache { //这个对象就是用来模拟hibernate一级缓存的 private static Map<Integer, Student> stus=new HashMap&l

  • 浅析Java的Hibernate框架中的缓存和延迟加载机制

    hibernate一级缓存和二级缓存的区别 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. Hibernate的缓存包括Sessi

  • 详解Java的Hibernate框架中的缓存与二级缓存

    缓存 今天我们就来讲一下hibernate中实体状态和hibernate缓存.  1)首先我们先来看一下实体状态:  实体状态主要分三种:transient,persitent,detached.  看英文应该就大概明白了吧.  transient:是指数据还没跟数据库中的数据相对应.  persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中.  detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响.

  • Hibernate框架中的缓存技术详解

    本文实例讲述了Hibernate框架中的缓存技术.分享给大家供大家参考,具体如下: Hibernate框架的缓存分为Session的缓存.SessionFactory的缓存,也称为一级缓存和二级缓存. 一级缓存: 一级缓存是Session级的缓存,其生命周期很短,与Session相互对应,由Hibernate进行管理,属于事务范围的缓存.当程序调用 Session的load()方法.get()方法.save()方法.saveOrUpdate()方法.update()方法或查询接口方法时,Hibe

  • hibernate查询缓存详细分析

     一.查询缓存配置 1.在hibernate.cfg.xml中加入查询缓存的策略,  <propertyname="hibernate.cache.use_query_cache">true</property>      启用查询缓存的策略,默认是false. 二.关闭二级缓存,采用query.list()查询普通属性 代码如下所示. public voidtestCache1() { Session session = null; try { session

  • MySQL的查询缓存机制基本学习教程

    MySQL缓存机制简单的说就是缓存sql文本及查询结果,如果运行相同的sql,服务器直接从缓存中取到结果,而不需要再去解析和执行sql.如果表更改 了,那么使用这个表的所有缓冲查询将不再有效,查询缓存值的相关条目被清空.更改指的是表中任何数据或是结构的改变,包括INSERT.UPDATE. DELETE.TRUNCATE.ALTER TABLE.DROP TABLE或DROP DATABASE等,也包括那些映射到改变了的表的使用MERGE表的查询.显然,这对于频繁更新的表,查询缓存是不适合的,而

  • 详细解读Hibernate的缓存机制

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为"Session的

  • Java详细分析讲解自动装箱自动拆箱与Integer缓存的使用

    目录 1. 前言 2. 包装类 3. 自动装箱与自动拆箱 4. Interger缓存 5. 回答题目 1. 前言 自动装箱和自动拆箱是什么?Integer缓存是什么?它们之间有什么关系? 先来看一道题目. Integer a = new Integer(1); Integer b = new Integer(1); System.out.println(a==b); Integer c = 1; Integer d = 1; System.out.println(c==d); Integer e

  • mysql详细分析讲解子查询的使用

    出现在其他语句中的 select 语句,称为子查询或内查询:外部的查询语句,称为主查询或 外查询 . -- 子查询 -- 查询的条件来自于另一查询的结果 SELECT * FROM t_user WHERE number=(SELECT number FROM t_user WHERE NAME='张三') 当然子查询也有类型,分为以下几种 : 标量子查询(结果集只有一行一列) 列子查询(结果集只有一列多行) 行子查询(结果集有一行多列)(较少) 表子查询(结果集一般为多行多列) 这里我们以新建

  • MyBatisPlus超详细分析条件查询

    目录 解决日志冗长的问题 构建条件查询 多条件构建 null判定 解决日志冗长的问题 不过测试的时候,控制台打印的日志比较多,速度有点慢而且不利于查看运行结果,所以接下来我们把这个日志处理下: 取消初始化spring日志打印,resources目录下添加logback.xml,名称固定,内容如下: <?xml version="1.0" encoding="UTF-8"?> <configuration> </configuration

  • hibernate和mybatis对比分析

    第一章     Hibernate与MyBatis Hibernate 是当前最流行的O/R mapping框架,它出身于sf.net,现在已经成为Jboss的一部分. Mybatis 是另外一种优秀的O/R mapping框架.目前属于apache的一个子项目. MyBatis 参考资料官网:http://www.mybatis.org/core/zh/index.html Hibernate参考资料: http://docs.jboss.org/hibernate/core/3.6/refe

  • 详细分析Redis集群故障

    故障表象: 业务层面显示提示查询redis失败 集群组成: 3主3从,每个节点的数据有8GB 机器分布: 在同一个机架中, xx.x.xxx.199 xx.x.xxx.200 xx.x.xxx.201 redis-server进程状态: 通过命令ps -eo pid,lstart | grep $pid, 发现进程已经持续运行了3个月 发生故障前集群的节点状态: xx.x.xxx.200:8371(bedab2c537fe94f8c0363ac4ae97d56832316e65) master

  • MyBatis高级映射和查询缓存

     mybatis框架执行过程: 1.配置mybatis的配置文件,SqlMapConfig.xml(名称不固定) 2.通过配置文件,加载mybatis运行环境,创建SqlSessionFactory会话工厂 SqlSessionFactory在实际使用时按单例方式. 3.通过SqlSessionFactory创建SqlSession SqlSession是一个面向用户接口(提供操作数据库方法),实现对象是线程不安全的,建议sqlSession应用场合在方法体内. 4.调用sqlSession的方

  • mysql的查询缓存说明

    对mysql查询缓存从五个角度进行详细的分析:Query Cache的工作原理.如何配置.如何维护.如何判断查询缓存的性能.适合的业务场景分析. 工作原理 查询缓存的工作原理,基本上可以概括为:缓存SELECT操作或预处理查询(注释:5.1.17开始支持)的结果集和SQL语句:新的SELECT语句或预处理查询语句,先去查询缓存,判断是否存在可用的记录集,判断标准:与缓存的SQL语句,是否完全一样,区分大小写: 查询缓存对什么样的查询语句,无法缓存其记录集,大致有以下几类:查询语句中加了SQL_N

随机推荐