hibernate笔记--缓存机制之 二级缓存(sessionFactory)和查询缓存

简介: 二级缓存(sessionFactory):   Hibernate的二级缓存由SessionFactory对象管理,是应用级别的缓存。它可以缓存整个应用的持久化对象,所以又称为“SessionFactory缓存”.   hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。

二级缓存(sessionFactory):

  Hibernate的二级缓存由SessionFactory对象管理,是应用级别的缓存。它可以缓存整个应用的持久化对象,所以又称为“SessionFactory缓存”.

  hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据;否则查询数据库

  下面介绍在hibernate中如何开启和使用二级缓存:

  1.在hibernate.cfg.xml中开启二级缓存,并且配置cache.region.factory_class:

<!-- 开启二级缓存 -->
    <property name="cache.use_second_level_cache">false</property>
    <!-- 配置cache.region.factory_classs -->
    <property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

  2:导入第三方jar包,(下载hibernate资源包,会在\lib\optional\ehcache文件夹下找到相关jar包):

  3.在src目录下,新建ehcache.xml.或在hibernate资源包的\project\etc目录下找到该文件,copy到src目录下:

    ehcache.xml:

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <!-- 
        maxElementsInMemory:设置存放对象数量的最大值
        eternal:设置是否永久存储
        timeToIdleSeconds:设置对象的空闲时间
        timeToLiveSeconds:设置对象的存活时间
        overflowToDisk:内存溢出是否写入磁盘
     -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /></ehcache>

  4:在需要使用二级缓存的实体类的hbm.xml文件中设置,或在hibernate.cfg.xml中指定需要使用二级缓存的实体类:

    以上一节的Book和Category为例,如果我需要开启Book的二级缓存:

      *在Book.hbm.xml文件中的class标签下,添加一个标签:

      <cache usage="read-only"/>

      *或在hibernate.cfg.xml的mapping属性下面,添加:

      <class-cache usage="read-only" class="com.wang.pojo.Book"/>

    关于usage的取值,有以下几种:

只读缓存(read-only):如果应用程序需要读取一个持久化类的实例,但是并不打算修改它们,可以使用read-only缓存。这是最简单,也是实用性最好的策略.

读/写缓存(read-write): 如果应用程序需要更新数据,可能read-write缓存比较合适。如果需要序列化事务隔离级别,那么就不能使用这种缓存策略。

不严格的读/写缓存(nonstrict-read-write):如果程序偶尔需要更新数据(也就是说,出现两个事务同时更新同一个条目的现象很不常见),也不需要十分严格的事务隔离,可能适用nonstrict-read-write缓存。

事务缓存(transactional):  transactional缓存策略提供了对全事务的缓存,仅仅在受管理环境中使用。它提供了Repeatable Read事务隔离级别。对于经常被读但很少修改的数据,可以采用这种隔离类型,因为它可以防止脏读和不可重复读这类的并发问题。

以上配置工作全部完成,我们来用代码,感受一下二级缓存的存在:

      Session session=HibernateUtil.getSession();
        Book book =(Book) session.get(Book.class,1);
        System.out.println(book.getName());
        session.beginTransaction().commit();
        session.close();
        System.out.println(book.getName());

在这段代码中,我先查询了一下id=1的Book信息,然后关闭了session对象,很明显一级缓存肯定是不存在了,然后我再次打印book的name,我们先看看控制台的打印信息:

神奇的是发生了,居然没有报错,而且打印出了book的name,这就是二级缓存的作用.现在我们再来看看开头的第二段内容,就一目了然了.

hibernate二级缓存中的缓存对象可以被整个应用的Session对象共享,即使关闭当前Session对象,新建的Session对象仍可使用。使用Hibernate的二级缓存之后查询数据,Session对象会首先在以及缓存中查找有无缓存数据被命中。如果没有,则查找二级缓存。如果有,则直接返回所命中的数据;否则查询数据库

 

查询缓存:

  查询缓存缓存的是查询出来的实体的部分属性结果集和实体的ID(注意这里不是实体).关于查询缓存和二级缓存的同时和分开使用的情况,网络上这一段解释的比较好,这里直接引用了:

当只是用Hibernate查询缓存而关闭二级缓存的时候: 
  第一:如果查询的是部分属性结果集: 那么当第二次查询的时候就不会发出SQL,直接从Hibernate查询缓存中取数据;
  第二:如果查询的是实体结果集eg(from Student) ,首先Hibernate查询缓存存放实体的ID,第二次查询的时候就到Hibernate查询缓存中取出ID 一条一条的到数据库查询,这样,将发出N 条SQL造成了SQL泛滥。

当都开启Hibernate查询缓存和二级缓存的时候:
  第一:如果查询的是部分属性结果集: 这个和上面只是用Hibernate查询缓存而关闭 二级缓存的时候一致,因为不涉及实体不会用到二级缓存;
  第二:如果查询的是实体结果集eg(from Student),首先Hibernate查询缓存存放实体的ID,第二次查询的时候,就到Hibernate查询缓存中取出ID,到二级缓存区找数据,如果有数据,就不会发出SQL;如果都有,一条SQL都不会发出,直接从二级缓存中取数据。

下面介绍如何开启和使用查询缓存:

  1.在hibernate.cfg.xml中.添加一个标签语句:

   <!-- 开启查询缓存 -->
    <property name="cache.use_query_cache">true</property>

  2.在代码中添加query.setCachemodel(true);

    List<Book> list =(List) session.createQuery("from Book")
                              .setCacheable(true)//使用查询缓存
                              .list();
        System.out.println(list.get(0).getName());
        session.beginTransaction().commit();
        session.close();
        System.out.println(list.get(0).getName());

这里使用了list(),查询所有Book信息,关闭session以后再次打印list中的内容,依然能打印出来,不会报错,这就是查询缓存的使用.

注意:

  查询缓存的生命周期与Session无关(可以跨Session查询),当查询关联的表发生改变,那么查询缓存的生命周期结束(delete、update、modify)

  查询缓存是专为Query的list方法设计的。对于iterate()方法,无论是查询对象属性还是对象本身,查询缓存用与不用都没有区别!

相关文章
|
20天前
|
缓存 NoSQL 安全
【Redis系列笔记】缓存三剑客
缓存穿透是指请求一个不存在的数据,缓存层和数据库层都没有这个数据,这种请求会穿透缓存直接到数据库进行查询。它通常发生在一些恶意用户可能故意发起不存在的请求,试图让系统陷入这种情况,以耗尽数据库连接资源或者造成性能问题。 缓存击穿发生在访问热点数据,大量请求访问同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据库资源,导致数据库无法使用。 缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。
41 1
|
1月前
|
缓存 关系型数据库 MySQL
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
MySQL 查询优化:提速查询效率的13大秘籍(索引设计、查询优化、缓存策略、子查询优化以及定期表分析和优化)(中)
|
6天前
|
存储 缓存 运维
【Docker 专栏】Docker 镜像的分层存储与缓存机制
【5月更文挑战第8天】Docker 镜像采用分层存储,减少空间占用并提升构建效率。每个镜像由多个层组成,共享基础层(如 Ubuntu)和应用层。缓存机制加速构建和运行,通过检查已有层来避免重复操作。有效管理缓存,如清理无用缓存和控制大小,可优化性能。分层和缓存带来资源高效利用、快速构建和灵活管理,但也面临缓存失效和层管理挑战。理解这一机制对开发者和运维至关重要。
【Docker 专栏】Docker 镜像的分层存储与缓存机制
|
12天前
|
缓存 NoSQL Java
17:缓存机制-Java Spring
17:缓存机制-Java Spring
40 5
|
13天前
|
缓存 编解码
FFmpeg开发笔记(十四)FFmpeg音频重采样的缓存
FFmpeg在视频流重编码和音频重采样中使用缓存机制。在音频文件格式转换时,特别是对于帧长度不固定的格式如ogg、amr、wma,需处理重采样缓存。通过调用`swr_convert`,传入空输入和0大小来清空缓存。在`swrmp3.c`中,修改帧样本数处理,并在循环结束后添加代码以冲刷缓存。编译并运行程序,将ogg文件重采样为MP3,日志显示操作成功,播放转换后的文件确认功能正常。
FFmpeg开发笔记(十四)FFmpeg音频重采样的缓存
|
13天前
|
存储 缓存 自然语言处理
深入PHP内核:探索Opcode缓存机制
【5月更文挑战第1天】 在动态语言如PHP的执行过程中,每次脚本被请求时都需要经过一系列复杂的解析和编译步骤。为了优化这一过程并提高性能,PHP引入了Opcode缓存机制。本文将详细探讨Opcode的概念、作用以及它如何显著提升PHP应用的执行效率。我们将从缓存原理出发,分析几种常见的Opcode缓存工具,并通过实例说明如何在实际项目中实现和优化缓存策略。
|
15天前
|
存储 缓存 Java
【Spring系列笔记】依赖注入,循环依赖以及三级缓存
依赖注入: 是指通过外部配置,将依赖关系注入到对象中。依赖注入有四种主要方式:构造器注入、setter方法注入、接口注入以及注解注入。其中注解注入在开发中最为常见,因为其使用便捷以及可维护性强;构造器注入为官方推荐,可注入不可变对象以及解决循环依赖问题。本文基于依赖注入方式引出循环依赖以及三层缓存的底层原理,以及代码的实现方式。
24 0
|
15天前
|
缓存 NoSQL PHP
【PHP开发专栏】PHP缓存机制与实现
【4月更文挑战第29天】本文介绍了PHP缓存的基本概念、策略及实现方式。PHP缓存包括应用缓存、Web服务器缓存、数据库缓存和分布式缓存,常见策略有缓存预热、更新和懒加载。PHP的缓存实现包括文件缓存、APC、OPcache、Memcached和Redis。最佳实践包括缓存热点数据、控制粒度、设置失效策略、保证一致性和确保安全性。文中还提供了一个新闻列表和详情页的缓存实战示例,帮助开发者理解如何在实际项目中应用缓存。
|
21天前
|
缓存 流计算
缓存命中率和过期机制的一般思路
【4月更文挑战第20天】缓存命中率是评估缓存效果的关键,目标是达到90%以上,但某些频繁的小请求场景可能无法实现。过期机制可采用定时删除(精确但开销大)、延迟队列(精确但有队列开销)、懒惰删除(简单但时间不精确)或定期删除(简单但性能损耗不可控)。
19 4
|
21天前
|
缓存 Linux
linux系统缓存机制
linux系统缓存机制