IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Mybatis二级缓存源码剖析 -> 正文阅读

[Java知识库]Mybatis二级缓存源码剖析

?级缓存构建在?级缓存之上,在收到查询请求时,MyBatis 首先查询?级缓存,若?级缓存未命 中,再去查询?级缓存,?级缓存没有,再查询数据库。

与?级缓存不同,?级缓存和具体的命名空间绑定,?个Mapper中有?个Cache,相同Mapper中的 MappedStatement公用?个Cache,?级缓存则是和 SqlSession 绑定

一,全局二级缓存开启配置

<settings>
 <setting name="cacheEnabled" value="true"/>
</settings>

方向:通过配置开启二级缓存,源码剖析从配置读取生效入手

还是如同Mybatis之前的解析步骤一样,从Mybatis初始化读取配置入手,进入到XMLConfigureBuilder类中的parse方法。

然后继续往下层去剥,根据上面的开启全局二级缓存配置,找到parseConfiguration中的解析Setting标签的部分。

?二,Mapper中的Cache标签解析与对象构建

全局二级缓存开启之后,对于使用二级缓存的Mapper.xml需要在Mapper标签内进行如下的配置:

<cache></cache>。

从配置中可以知道,二级缓存绑定Mapper,真正去调用绑定应该还是在Mapper标签解析的时候去执行的。承接上面的解析代码进到mapperElement方法当中去,然后判断是指根据何种方式去读取的Mapper配置加载方式。读取的方式不会决定Mapper读取后处理的步骤,这里从路径配置的else条件中parse方法进入。

?一直往下走到这里为止,则看到了Mapper解析时,解析cache标签的地方了。上面的cache-ref表示的是从别的地方去取缓存数据,这里不做多的深入探究,继续看cacheElement方法。

?进到cacheElement中后,可以看到对于cache标签,还提供了其它的属性配置。?上面部分的属性配置读取完成后,最后useNewCache则开始创建Cache对象,点进去看如何去构建的。

?进入到方法后,第一步实例化一个Cache对象,把之前的配置信息放入到对象中。然后第二步,是否是似曾相识?把构建好的Cache对象存入到Configuration对象当中去。之前的解析主线源码的时候有说过这个对象,解析出来的内容放入到Configuration对象然后一直向下传递。第三步则是把构建的新的二级缓存对象复制给buildAssistant类中的currentCache。

?到这里为止,可以发现对于一个Mapper Cache对象只在初始化时候创建一次,符合?个Mapper中有?个Cache对象。但是相同的Mapper中公用一个Cache对象,之前主线源码解析有说过Mapper对象在解析后会整合了存入到Configuration中的MappeStatement容器中去,那么对于相同的Mapper读取整合后,Cache对象是否应该去绑定进去?

回到之前Mapper解析的方法中去,从buildStatementFromContext方法进去,这个方法之前有提到过,对于整合解析好的Mapper会存入到MappeStatement当中去。然后对于判断不论如何都会去调用buildStatementFromContext方法,直接点进该方法。

?然后看到又构建了一个XMLBuilder,然后去解析MappeStatement,这里的代码之前主线解析也有提到过。进入到parseStatementNode方法,重要看关于cache的部分,之前该方法的完整部分也有在主线解析时贴出来,这里直接看重点的几行代码。

flushCache都不陌生,对于每次数据库操作是否都去刷新当前缓存,后面的useCache则是是否使用二级缓存.

然后该方法往下拉,到构建MappeStatement,注意这里的对象buildAssistant,上面有提到过该对象,对于创建的Cache对象第三步,会赋值给buildAssistant类中的currentCache。

?进入到该方法之后,对于之前的CurrentCache对象,会在MappeStatement构建的过程中进行绑定。?到这里位置Cache标签的解析,Cache对象的构建,传入与绑定则全部剖析完成。

三,二级缓存执行流程剖析

SQL执行的过程中如何从二级缓存中存入和拿取数据?既然涉及了SQL的执行,那么从直接从SqlSession中的常用数据操作方法入手,这里就从SqlSession中的SelectList入手。(为什么不从selectOne?selectOne底层也是并入到selectList中去委派Excutor执行的)

?通过Debug模式可以发现,在开启了二级缓存后,executor的执行方式和之前主线源码解析的不同了,它会跳转到CachingExecutor中去委派执行SQL操作。

?进入到CachingExecutor中的query方法,BoundSql对于参数#{}与?的转换,参数的传入,之前主线代码解析有提到过,这里不多做分析,这里创建了一个CacheKey,然后去执行查询的操作。

?进入到query方法后,注意几个方面:

1,cache标签上面解析最后的步骤时,会对于MappedStatement进行绑定,确定相同的MappeStatement公用一个Cache对象,这里从MappedStatement中获取Cache对象

2,上面有提到过的Cache标签中还能够去配置的一些参数,比如是否有用到二级缓存的UseCache,Mapper解析时,是否每次操作都要清空缓存的数据flushCache。

3,这里的tcm是一个二级缓存的事务管理器,它的作用就是从二级缓存的中去取数据,因为是第一次操作,list肯定是空的,那么走到下面的delegate

4,delegate可以看到是一个excutor,它负责去执行做SQL操作,这里的executor通过Debug去执行,会发现它跳转到了BaseExecutor中去,如同主线执行一样,会从一级缓存中去拿结果。

?但是第一次执行肯定一级缓存中也没有数据,那么则会从数据库中去拿数据,然后存入到本地缓存,也就是所谓的一级缓存。

?数据存入到了一级缓存中了,上面的代码中有这样一个存放数据的操作,这个操作时进行二级缓存吗?

点进去后到TransactionalCacheManager对象,对象中对Cache作为Key去再封装了一层,这里为什么不直接使用Cache对象呢?Cache对象在一个MappeStatement中的唯一性,如果直接获取,多请求并发时会导致线程的不安全性,所以把缓存的数据放入到了一个TransactionCache中去。

?继续往下走,到TransactionalCache对象中,这里把查询的数据存入到了该对象的Set集合中,那么问题来了,到这里为止,数据都没有存入到二级缓存中去,这里的存入到Set中是因为事务性,回滚操作下防止二级缓存的频繁存取。

在TransactionalCache中可以看到commit方法,二级缓存只对提交的事务会写入。commit中,delegate是否似曾相识?之前二级缓存的获取,就是从tcm的get方法,就从这里获取的,它就是一个二级缓存的对象。

?然后去看flushPendingEntries方法,entriesToAddOnCommit这个容器已经提到过了,这里从容器中获取未提交的容器中的数据存入到二级缓存。到这里为止,可以发现二级缓存对于没有提交的数据是不具备缓存作用的,如果没有提交,delegate缓存对象永远是一个null值,永远拿不到数据。

四,二级缓存的刷新机制?

二级缓存的刷新无非在于SQL进增删改操作时的缓处理。还是SqlSession当中去,去看非查询的操作,这里从更新操作着手。还是会判断update标签中是否加入了flushCache属性。update操作之前都会去执行一次select操作,第一次执行flush方法时候,利用debug跟踪,因为下面的参数为false不会去清空二级缓存,但是在查询之后会对该参数重新赋值为true,在第二次执行时,这里的判断就是true了,则会情空二级缓存。

然后继续往下走,到BaseExecutor中去,到这里更新完会清空本地的缓存数据,也就是一级缓存的数据,然后执行doUpdate方法完成更新。

?

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-22 13:25:07  更:2021-08-22 13:26:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 20:40:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码