Mybatis缓存理解
缓存
接触过hibernate的同学都知道hibernate中有个二级缓存,mybatis也存在二级缓存。mybatis中二级缓存有什么作用呢?mybatis提供查询缓存,可以提高查询效率,减轻数据库的压力。
一级缓存
一级缓存是session级别的缓存,基于PerpetualCache的HashMap本地存储,其存储作用域为Session,不能跨不同的session,当Session flush或close之后,该Session中的所有Cache就将清空。
SqlSession session = sqlSessionFactory.openSession();
FootballMatchMapper footballMatchMapper = session.getMapper(FootballMatchMapper.class);
FootballMatch footballMatch = footballMatchMapper.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName()); //重复查询同一条记录时,一级缓存开始使用
footballMatch = footballMatchMapper.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName()); //session关闭,session中的cache将被清除
session.close();
session = sqlSessionFactory.openSession();
footballMatchMapper = session.getMapper(FootballMatchMapper.class);
footballMatch = footballMatchMapper.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName()); footballMatch = footballMatchMapper.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName()); //sqlSession执行insert、update、delete等操作commit提交后会清空缓存区域
footballMatch.setUpdateTime(new Date());
footballMatchMapper.updateByPrimaryKeySelective(footballMatch);
footballMatch = footballMatchMapper.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName());
通过日志分析一下:
同一个session作用域内,相同查询结果会从缓存中取,不会重复从数据库查询。当session关闭之后,该Session中的所有Cache就将清空,从而从数据库查询:

update操作之后会清空缓存区域,使缓存失效,从而执行数据库查询:

二级缓存
二级缓存是mapper级别的缓存,它的实现机制跟一级缓存差不多,也是基于PerpetualCache的HashMap本地存储。作用域为mapper的namespace,可以自定义存储,比如Ehcache。Mybatis的二级缓存是跨Session的,每个Mapper享有同一个二级缓存域.
Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的Java对象。
SqlSession session1 = sqlSessionFactory.openSession();
FootballMatchMapper footballMatchMapper1 = session1.getMapper(FootballMatchMapper.class);
FootballMatch footballMatch = footballMatchMapper1.selectByPrimaryKey("20180115004");
System.out.println(footballMatch.getHomeTeamName());
session1.close(); SqlSession session2 = sqlSessionFactory.openSession();
FootballMatchMapper footballMatchMapper2 = session2.getMapper(FootballMatchMapper.class);
FootballMatch footballMatch2 = footballMatchMapper2.selectByPrimaryKey("20180115004");
System.out.println(footballMatch2.getHomeTeamName());
session2.close();

如果两个mapper文件的命名空间一样,他们就可以共享一个mapper缓存。每次查询会先从缓存区域找,如果找不到从数据库查询,查询到数据将数据写入缓存。
开启缓存
二级缓存是需要配置来开启的:
<setting name="cacheEnabled" value="true"/>
非常简单,在Mybatis的核心配置文件中加上上面这行代码,然后在Mapper映射文件中添加一行:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
表示开启二级缓存,flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。 readOnly(只读)属性可以被设置为true或false。
只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
如果已经开启二级缓存的mapper里面某个查询不需要缓存,可以使用useCache=”false”禁用二级缓存:
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" useCache="false">
刷新缓存
在mapper的同一个namespace中,如果有其他insert、update、delete操作后都需要执行刷新缓存操作,来避免脏读。
这时我们只需要设置statement配置中的flushCache=“true“属性,就会默认刷新缓存,相反如果是false就不会了。
当然,不管开不开缓存刷新功能,你要是手动更改数据库表,那都肯定不能避免脏读的发生,那就属于手贱了。
无论是一级缓存还是二级缓存,C/U/D增删改操作commit提交后会清空缓存区域,使缓存失效。合理利用二级缓存可以提高系统性能,减少数据库压力。但是,如果使用不当可那个会出现缓存一致性问题,对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度。
本文转自:https://blog.csdn.net/chengbinbbs/article/details/79215783
Mybatis缓存理解的更多相关文章
- 《深入理解mybatis原理4》 MyBatis缓存机制的设计与实现
<深入理解mybatis原理> MyBatis缓存机制的设计与实现 本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存 ...
- mybatis缓存的设计
继续用提问的方式来看Mybatis的缓存设计. 1.Mybatis如何开启缓存 Mybatis对查询结果进行缓存,所以缓存的对象为具体的Statement 通过在Statement上是否使用缓存来启用 ...
- Mybatis 缓存分析
其实本来不想专门的写一篇关于mybatis缓存的博客的.在之前的博客中已经大致的把mybatis的整体流程讲了一遍.只要按照步骤一步步的点进去,关于缓存的代码很容易就能发现.但是今天在看代码的时候突然 ...
- 【转】MaBatis学习---源码分析MyBatis缓存原理
[原文]https://www.toutiao.com/i6594029178964673027/ 源码分析MyBatis缓存原理 1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 ...
- 聊聊MyBatis缓存机制【美团-推荐】
聊聊MyBatis缓存机制 2018年01月19日 作者: 凯伦 文章链接 18778字 38分钟阅读 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用My ...
- MyBatis缓存通俗易懂
1.1 mybatis缓存介绍 如下图,是mybatis一级缓存和二级缓存的区别图解: Mybatis一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的 ...
- MyBatis缓存设计
和大多数ORM框架一样,为了尽可能减少数据库的访问,MyBatis设计支持缓存功能.设计上通过Cache接口提供SPI(服务提供接口),可以让第三方缓存提供具体的缓存实现,比如使用ehcache.Re ...
- 聊聊MyBatis缓存机制
https://tech.meituan.com/mybatis_cache.html 前言 MyBatis是常见的Java数据库访问层框架.在日常工作中,开发人员多数情况下是使用MyBatis的默认 ...
- 【转】MyBatis缓存机制
转载:https://blog.csdn.net/bjweimengshu/article/details/79988252. 本文转载自公众号 美团技术点评 前言 MyBatis是常见的Java数据 ...
随机推荐
- C语言学习笔记 (007) - 数组指针和通过指针引用数组元素的方法总结
1.数组指针:即指向数组的指针 那么, 如何声明一个数组指针呢? ]; /*括号是必须写的,不然就是指针数组:10是数组的大小*/ 拓展:有指针类型元素的数组称为指针数组. 2.通过指针引用数组元素的 ...
- EF的表左连接方法Include和Join
在EF中表连接常用的有Join()和Include(),两者都可以实现两张表的连接,但又有所不同. 例如有个唱片表Album(AlbumId,Name,CreateDate,GenreId),表中含外 ...
- 【MySQL】MySQL存储过程介绍
目录结构: contents structure [-] 存储过程简介 关于MySQL的存储过程 MySQL存储过程的创建 格式 声明分割符 参数 变量 注释 MySQL存储过程的调用 MySQL存储 ...
- 【javascript】js中的函数节流和函数防抖
一.概念解释 函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段. 大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变 ...
- OpenCV 学习笔记03 边界框、最小矩形区域和最小闭圆的轮廓
本节代码使用的opencv-python 4.0.1,numpy 1.15.4 + mkl 使用图片为 Mjolnir_Round_Car_Magnet_300x300.jpg 代码如下: impor ...
- 关于ps cs5的一些问题
一.photoshop cs5 默认在窗口中浮动方法 1.打开“编辑>首选项>界面”在“面板和文档”里把“以选项卡方式打开图像”的勾选去掉 2.点击菜单栏“窗口>排列>使所有内 ...
- Android适配底部返回键等虚拟键盘的完美解决方案
这个问题来来回回困扰了我很久,一直没能妥善解决. 场景1:华为手机遮挡了屏幕底部. 场景2:进入应用时,虚拟键自动缩回,留下空白区域. 需求: 需要安卓能自适应底部虚拟按键,用户隐藏虚拟按键时应用要占 ...
- com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024)
### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024). You ...
- shell脚本监控Linux系统的登录情况
一.登录日志记录 vi /etc/profile 在最后面添加一行: echo "`who`" > /var/log/login.log 二.监控日志文件 #!/bin/ba ...
- stm8 I/O口模式配置
复位后的默认配置 :复位之后,所有的引脚都是悬浮输入模式. However, a few pins may have a different behavior. Refer to the datash ...