Mybatis的二级缓存

1、二级缓存的范围

 1. 二级缓存是Mapper级别的缓存。

 2. 二级缓存的结构也是一个HashMap。

 3. 不同的SqlSession对象去操作同一个mapper中的SQL语句,多个SqlSession共用二级缓存。

 4. 二级缓存的作用域是mapper的同一个namespace,如果两个mapper文件的namespace相同,则这两个共用二级缓存。

 5. Mybatis的二级缓存需要配置开启。

2、工作原理

说明:

 1. 当SqlSession1一次执行查询的时候,首先会去查询二级缓存,如果二级缓存中没有数据,然后才回去查询数据库,数据库返回后会将返回的数据保存到二级缓存之中。

 2. 第二次SqlSession2再去查询相同的数据时,就会直接从二级缓存中取数据,不再需要去查询数据库。

 3. 如果在两次查询之间执行了SqlSession3的commit操作(执行插入、更新、删除),则会清空二级缓存,这样是为了防止读到脏数据。

3、一级缓存的测试

 1. 开启二级缓存

  mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,还要在具体的mapper.xml中开启二级缓存。

 2. SqlMapConfig.xml中开启二级缓存

<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true" />
</settings>

 3. po实现序列化

  二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。

 4. mapper.xml文件中配置缓存

	<mapper namespace="com.jack.dao.Mapper">
<!--开启本mapper的二级缓存-->
<cache />
<select id="findUser" parameterType="int" resultType="User">
SELECT * FROM User WHERE id = #{value}
</select> <select id="updateUser" parameterType="User" >
UPDATE User SET username=#{username} WHERE id = #{id}
</select>
</mapper>

 5. mapper接口文件

 public User findUser(int id) throws Exception;
public User updateUser(User user) throws Exception;

 6. 测试代码

 public void testErCache() throws Exception{
SqlSession session1 = sessionFactory.openSession();
Mapper mapper1 = session1.getMapper(Mapper.class);
//第一次查询,会发送SQL语句,去数据库查询
User user1 = mapper1.findUser(1);
System.out.println(user1);
//必须执行SqlSession的close操作,才会将数据写入二级缓存
session1.close();
//执行修改的commit操作
SqlSession session2 = sessionFactory.openSession();
Mapper mapper2 = session2.getMapper(Mapper.class);
User user2 = mapper2.findUser(1);
user2.setUsername("小明");
mapper2.updateUser(user2);
session2.commit();
session2.close();
//第二次查询,如果没有执行commit操作,直接在缓存中取数据,不会发生sql语句查询数据库
//如果执行了commit操作,会发生sql语句查询数据库
SqlSession session3 = sessionFactory.openSession();
Mapper mapper3 = session3.getMapper(Mapper.class);
User user3 = mapper3.findUser(1);
System.out.println(user3);
session3.close();
}

4、禁用二级缓存

在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。

 <select id="findUser" parameterType="int" resultType="User" useCache="false">
SELECT * FROM User WHERE id = #{value}
</select>

5、刷新缓存

在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。

设置statement配置中的flushCache="true" 属性,默认情况下为true即刷新缓存,如果改成false则不会刷新。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

<select id="findUser" parameterType="int" resultType="User" useCache="false" flushCache="true">
SELECT * FROM User WHERE id = #{value}
</select>

6、Mybatis Cache参数详解

(1)flushInterval(刷新间隔):可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

(2)size(引用数目):可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。

(3)readOnly(只读)属性:可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

如下例子:

<cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:

  1. LRU – 最近最少使用的:移除最长时间不被使用的对象。
  2. FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
  4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

7、二级缓存的应用场景

 对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。

  实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

8、二级缓存的局限性

 mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

9、使用ehcache来管理Mybatis的缓存

 1. ehcache简介

   Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。

 2. 与Mybatis联合的原理

  Mybatis提供了一个拥有管理缓存的接口Cache,只要实现Cache接口,就可以自己来处理Mybatis的缓存逻辑,ehcache实现了该接口。

 3. 实现步骤:

  (1). 加入ehcache的jar包。

  

  (2). 创建ehcache的配置文件

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!--
指定数据在磁盘中的存储位置
-->
<diskStore path="F:\develop\ehcache" />
<!--
 defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
 maxElementsInMemory - 在内存中缓存的element的最大数目
 maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
 eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
 overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
 timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
 timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
 diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
 diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
 memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
<defaultCache maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>

  (3). 在mapper.xml指定ehcache为缓存处理器

 <!--
开启本mapper的二级缓存
指定缓存管理为ehcache
property可以不用进行配置
-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
<property name="timeToIdleSeconds" value="3600"/>
<property name="timeToLiveSeconds" value="3600"/>
<!-- 同ehcache参数maxElementsInMemory -->
<property name="maxEntriesLocalHeap" value="1000"/>
<!-- 同ehcache参数maxElementsOnDisk -->
<property name="maxEntriesLocalDisk" value="10000000"/>
<property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>

Mybatis缓存(二)的更多相关文章

  1. Spring Boot2(二):使用Spring Boot2集成Mybatis缓存机制

    前言 学习SpringBoot集成Mybatis的第二章,了解到Mybatis自带的缓存机制,在部署的时候踩过了一些坑.在此记录和分享一下Mybatis的缓存作用. 本文章的源码再文章末尾 什么是查询 ...

  2. MyBatis学习总结(四)——MyBatis缓存与代码生成

    一.MyBatis缓存 缓存可以提高系统性能,可以加快访问速度,减轻服务器压力,带来更好的用户体验.缓存用空间换时间,好的缓存是缓存命中率高的且数据量小的.缓存是一种非常重要的技术. 1.0.再次封装 ...

  3. mybatis缓存机制

    目录 mybatis缓存机制 Executor和缓存 一级缓存 小结 二级缓存 小结 mybatis缓存机制 mybatis支持一.二级缓存来提高查询效率,能够正确的使用缓存的前提是熟悉mybatis ...

  4. Mybatis系列(四):Mybatis缓存

    一.MyBatis缓存介绍 MyBatis 提供了一级缓存和二级缓存的支持        1. 一级缓存: 默认开启,基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Se ...

  5. 分享知识-快乐自己:Mybatis缓存机制

    论缓存机制: 1):mybatis 提供了缓存机制减轻数据库压力,提高数据库性能. 2):mybatis 的缓存分为两级:一级缓存.二级缓存 3):一级缓存是SqlSession级别的缓存,缓存的数据 ...

  6. mybatis缓存机制(转)

    缓存在互联网系统中是非常重要的, 其主要作用是将数据保存到内存中, 当用户查询数据 时, 优先从缓存容器中获取数据,而不是频繁地从数据库中查询数据,从而提高查询性能.目 前流行的缓存服务器有Mongo ...

  7. MyBatis笔记二:配置

    MyBatis笔记二:配置 1.全局配置 1.properites 这个配置主要是引入我们的 properites 配置文件的: <properties resource="db.pr ...

  8. mybatis缓存,包含一级缓存与二级缓存,包括ehcache二级缓存

    一,引言 首先我们要明白一点,缓存所做的一切都是为了提高性能.明白了这一点下面我们开始进入正题. 二,mybatis缓存概要 ①.mybatis的缓存有两种,分别是一级缓存和二级缓存.两者都属于查询缓 ...

  9. (四)mybatis缓存、事务、插件的基本知识

    mybatis缓存.事务.插件的基础 一.缓存 (一)一级缓存与二级缓存 一级缓存 为了获得更好的性能,最重要的就是一级缓存.每个session对象维持一个一级缓存,session对象创建时缓存创建, ...

  10. Mybatis缓存及延迟加载策略

    一:引言 通过前面几篇的文章介绍了Mybatis的一对一.一对多.多对多关系的配置及实现,可是大家发现了吗?在执行关联查询的时候,直接会把当前查询的主表里包含的副表也查询后封装到对象里,其实在实际开发 ...

随机推荐

  1. python3.5在内存中获取远程图片尺寸

    自已看看,用于获取选程图片的尺寸 >>> from io import BytesIO>>> import requests as rs>>> f ...

  2. Django_Restframwork_APIVIEW视图_源码分析

    Django _VIEW视图_源码分析

  3. 十八、Node.js创建Web服务器(二)

    在上一篇文章中我们在自定义模块自定义了几种文件类型的头文件加工的方法: /** * 自定义模块加工响应头文件类型 */ module.exports.getminiName=function (ext ...

  4. TVS

    TVS 电子电路中二极管是非常常见的元器件,按照材料主要分为锗二极管.硅二极管.按用途的不同又可分为瞬态二极管.整流二极管.检波二极管.稳压二极管.变容二极管.光电二极管.发光二极管.开关二极管.快速 ...

  5. 波利亚(Polya)罐子模型

    (波利亚(Polya)罐子模型)罐中有a个白球,b个黑球,每次从罐中随机抽取一球,观察其颜色后,连同附加的c个同色球   (波利亚(Polya)罐子模型)罐中有a个白球,b个黑球,每次从罐中随机抽取一 ...

  6. alicemq 方便的RabbitMQ 可视化工具

    尽管RabbitMQ 自带一个管理插件,但是还不是那么强大,alicemq 是一个方便强大的可视化工具 rabbitmq 环境准备 docker-compose 文件 version: "3 ...

  7. bzoj1800飞行棋

    题目链接 简单模拟 真的不敢相信ahoi09年的题竟然是这个难度 首先,一个必须要知道的定理是:圆上只有直径所对的圆周角是直角. 然后就很显然了, 只有两条不重合的直径上的四个点才能组成一个矩形, 所 ...

  8. QTREE5 - Query on a tree V(LCT)

    题意翻译 你被给定一棵n个点的树,点从1到n编号.每个点可能有两种颜色:黑或白.我们定义dist(a,b)为点a至点b路径上的边个数. 一开始所有的点都是黑色的. 要求作以下操作: 0 i 将点i的颜 ...

  9. 本地搭建GitLab

    现在很多企业都开始使用gitLab,因为他的权限管理强大,后台项目管理也很方便.下面就介绍本地搭建方法: 为避免损失,建议在虚拟机测试.虚拟机最低配置(内存2G,cpu:2核,硬盘:20G) 1.安装 ...

  10. 2016级算法第二次上机-C.AlvinZH的儿时梦想——坦克篇

    872 AlvinZH的儿时梦想----坦克篇 思路 简单题.仔细看题,题目意在找到直线穿过的矩形数最小,不能从两边穿过.那么我们只要知道每一行矩形之间的空隙位置就可以了. 如果这里用二维数组记住每一 ...