MyBatis功能点一:二级缓存cache
对于Mybatis缓存分作用域等维度区别一、二级缓存特点如下图:

分析缓存源码首先得找到缓存操作的入口:前面已经分析,sqlsesion.close()仅对一级缓存有影响,而update等对一/二级缓存均有影响。那从session为入口分析一级缓存,从mapper分析二级缓存。
对于缓存的作用域,之前文章五、MyBatis缓存初体验 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中已经验证,下面主要从底层数据结构这个维度理解一二级缓存。既然都是基于Perpetualcache的HashMap本地缓存,那么通过调试跟踪到其源码所在位置分析:

PerpetualCache是对JUC中Cache接口的实现,其核心结构为命名为cache的Map<Object, Object>;所以缓存实际就是一个附带id的HashMap。实际上是不是只要实现了JUC中Cache接口均可以作为Mybatis备用缓存???当然可以,可参考MyBatis缓存Cache包 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)。
一级缓存
跟踪调试仅使用一级缓存的代码,调试信息发现,
,
即可知SimpleExectutor或其上级父类中对一级缓存进行处理,跟踪调试信息,可得如下调用链(查看MyBatis中执行器Executor框架 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)):
一级缓存功能由BaseExecutor类实现,即意味着每个实际执行器都具有这一级的功能。

那么其具体应用逻辑为何?查看源码如下:

从源码分析可得:如果设置了每次查询都清缓存,那么每次查询清缓存。同时查询之前判断localCache中是否有当前查询statement.id的相应数据,如果有则直接从一级缓存中获取结果,否则进行查询数据库的操作。
二级缓存
二级缓存的作用范围是一个命名空间(即一个映射文件或多个mapper文件同一个命名空间),而且可以实现多个命名空间共享一个缓存。跟踪二级缓存,其建立在mapper配置文件解析过程中即建立,而不是在opensession中。

二级缓存默认开启,如取消采用如下配置:
<settings>
<setting name="cacheEnabled" value="false"/>
</settings>
注解方式在mapper接口中使用如下注解,二级缓存生效,否则开启亦不生效。同理在mapper.xml文件中也需配置<cache></cache>表示二级缓存生效
通过注解
开启二级缓存,查看注解源码

可知默认使用PerpetualCache的实现,通过implementation属性,说明二级缓存是可配置的。可以配置用户需要使用的第三方或自定义缓存,比如redis。
那二级缓存是如何工作的?我们开启二级缓存通过调试查看源码,如下:

可知CachingExecutor中首先查询二级缓存,如果查询结果为空则业务逻辑有simpleExecutor处理即一级缓存的使用逻辑。
开篇提到,sqlSession.close仅对一级缓存清空二级缓存无影响,以及update等操作对一二级缓存均清空,那么通过close和update源码分别来证实:

分析CachingExecutor中close的业务逻辑:

首先处理二级缓存rollback或者commit,再处理一级缓存赋值null。所以close操作会清空一级缓存,二级缓存强制回退或者提交数据。

分析CachingExecutor中update的业务逻辑,显然与close方法不同,如下:
在上面分析过程中都遇到了CachingExecutor的一个属性,tcm——啥玩意?TransactionalCacheManager

MyBatis将Cache,TransactionalCache做了映射,而不是和一级缓存保存一致,直接使用,这是为什么呢?下面附源码两张:


第一张图说明一级缓存直接在executor中活动,即作用范围为session;第二张图说明二级缓存在MappedStatement中活动,作用范围跨session了。同样证实了开篇提到的cache作用范围。也因为二级缓存的作用范围跨session,可以同时被多个session同时获取就出现了线程安全的问题,导致脏读问题。为了解决这一问题,就有了TransactionalCache及其Manager——就是tcm对应类。

从其类图中,可以直观的发现其增加了读写锁相关的功能。
MyBatis功能点一:二级缓存cache的更多相关文章
- mybatis 使用redis实现二级缓存(spring boot)
mybatis 自定义redis做二级缓存 前言 如果关注功能实现,可以直接看功能实现部分 何时使用二级缓存 一个宗旨---不常变的稳定而常用的 一级是默认开启的sqlsession级别的. 只在单表 ...
- Mybatis整合Redis实现二级缓存
Mybatis集成ehcache . 为什么需要缓存 拉高程序的性能 . 什么样的数据需要缓存 很少被修改或根本不改的数据 业务场景比如:耗时较高的统计分析sql.电话账单查询sql等 . ehcac ...
- mybatis精讲(六)--二级缓存
目录 简介 配置 源码 CachingExecutor 自定义二级缓存 # 加入战队 微信公众号 简介 上一章节我们简单了解了二级缓存的配置.今天我们详细分析下二级缓存以及为什么不建议使用二级缓存. ...
- myBatis源码解析-二级缓存的实现方式
1. 前言 前面近一个月去写自己的mybatis框架了,对mybatis源码分析止步不前,此文继续前面的文章.开始分析mybatis一,二级缓存的实现.附上自己的项目github地址:https:// ...
- SSM+redis整合(mybatis整合redis做二级缓存)
SSM:是Spring+Struts+Mybatis ,另外还使用了PageHelper 前言: 这里主要是利用redis去做mybatis的二级缓存,mybaits映射文件中所有的select都会刷 ...
- java:Mybatis框架3(二级缓存,延时和积极加载,SSI(Ibatis)集成,SSM集成)
1.二级缓存: 需要导入二级缓存jar包: mybatis03: ehcache.xml: <ehcache xmlns:xsi="http://www.w3.org/2001/XML ...
- Mybatis架构原理(二)-二级缓存源码剖析
Mybatis架构原理(二)-二级缓存源码剖析 二级缓存构建在一级缓存之上,在收到查询请求时,Mybatis首先会查询二级缓存,若二级缓存没有命中,再去查询一级缓存,一级缓存没有,在查询数据库; 二级 ...
- mybatis结合redis实战二级缓存(六)
之前的文章中我们意见分析了一级缓存.二级缓存的相关源码和基本原理,今天我们来分享下了mybatis二级缓存和redis的结合,当然mybatis二级缓存也可以和ehcache.memcache.OSC ...
- SpringMVC + MyBatis + Mysql + Redis(作为二级缓存) 配置
2016年03月03日 10:37:47 标签: mysql / redis / mybatis / spring mvc / spring 33805 项目环境: 在SpringMVC + MyBa ...
随机推荐
- vue 因为使用scope后选择器和标签出现[data-v
使用scope的以后出现datd-v,例如: <div data-v-2311c06a class="button-warp"> <button data-v-2 ...
- iframe页面二次登录问题
原文链接:iframe页面二次登录问题 生产问题 问题背景 由于历史原因,公司内部系统有一些页面是基于iframe嵌入的其他系统的页面,之前一直运行正常,最近不知什么原因接连出现访问所有iframe页 ...
- Kube-OVN1.5.0新版本发布,支持鲲鹏云平台网络平面部署
近日,Kube-OVN发布了最新的1.5.0版本.自2019年4月开源以来,Kube-OVN经历了15次重要版本迭代,以及社区成立,建设者贡献代码,稳定性测试,国内外用户开始在生产环境中投入使用,企业 ...
- 在 python 项目中如何记录日志
一. 概述 写本文的目的是我在写 python 项目的时候需要记录日志,我忘记怎么处理了,每次都需要去网上查一遍,好记性不如烂笔头, 这里把查阅的内容记录下来,方便以后查找. python 项目中记录 ...
- 性能优化-使用双buffer实现无锁队列
借助本文,实现一种在"读多写一"场景下的无锁实现方式 在我们的工作中,多线程编程是一件太稀松平常的事.在多线程环境下操作一个变量或者一块缓存,如果不对其操作加以限制,轻则变量值或者 ...
- fluem读取文件并写入到hadoop的hdfs
接上一章,本章介绍使用 crontab 像指定文件定时写入,使用fluem 读取并写入到hadoop的hdfs 前提准备已安装好fluem ,和hadoop(推荐单机即可毕竟做实验) 一.进入终端执行 ...
- Solon Web 开发,十三、WebSocket
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 设置图片DPI
//image 可以先转换为 bitmap Bitmap bmp = new Bitmap(width, height); bmp.SetResolution(300, 300);
- elementui表格里面的索引,多选的复用解决
使用elementui表格时,当一个页面通过if判断有多个不同的表格时,其中一个或多个表格想要设置索引或者多选框时,会发现你在第一个里面设置了索引或者多选框,其他的表格都会出现,你在后面的其中一个设置 ...
- golang中字符串、bytes类型切片、16进制字符串之间的转换
func main() { // 字符串转bytes类型 name := "马亚南" fmt.Println(name) // 马亚南 bName := []byte(name) ...