mybaitis源码分析二 CURD方法执行流程和一二级缓存处理

在mybatis当中实际上只有两种方法的执行,一是query二是update。所有的查询方法到最后都会取调用query,其它三种方法最后都会取调用update。之间提过mybatis实际上是jdbcTmeplate的封装,这里就体现出来了,那么接下来就开始学习吧。

一.方法的执行流程

先上两张图

请添加图片描述
请添加图片描述
可以看出两种方法都是通过执行器执行,通过sqlSession执行的各类selectXXX和增删改操作在做了动态sql和参数相关的封装处理后,都会交给对应的执行器去处理,包括一、二级缓存的管理,事务的具体管理,Statement和具体JDBC层面优化的实现等等,通过策略者模式来使用这些执行器。

那么执行器有那些类型呢?请添加图片描述
上图就是执行器的大概架构,值得注意的是下面三个执行器默认使用的是SimpleExecutor。这些执行器也都可以自己配置的,我没有仔细研究过,有兴趣可以自己研究一下。大概描述了这些东西后,开始方法的执行吧!

1.query方法的执行

在执行具体方法前先把二级缓存打开,二级缓存是需要配置打开的,如果不使用二级缓存可以不打开,但也是这个流程

首先在配置文件mybatis-config.xml当中编写

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

然后再对应的配置文件当中填写

<cache type="org.apache.ibatis.cache.impl.PerpetualCache"></cache>

type可以不配置,有默认配置的。

二级缓存在每个标签都有对应的控制,有是否打开二级缓存userCache和是否刷新二级缓存flushCache 两种配置。

userCache是用来设置是否禁用二级缓存的,useCache查询方法query默认为true,其他三种使用update的默认是false,在statement中设置useCache=false可以禁用当前select语句的二级缓存。

flushCache 属性,select方法默认情况下为false,其他三种方法默认是打开的。使用缓存时如果手动修改数据库表中的查询数据会出现脏读。

讲明白这些后我们开始执行方法
请添加图片描述
从上图可以看到query方法首先是取出sql和创建了一个key,key一般是map当中才会用到难道下面会使用到map吗?接着往下面看请添加图片描述
首先查看刷新缓存,查看一下是否和上面判断一样select默认关闭!

请添加图片描述请添加图片描述
果然一致。

接下来看二级缓存开启后是否默认打开

请添加图片描述

确实是默认打开的,上面图片可以发现key确实是用来取数据了,
怎么取的呢?
请添加图片描述
请添加图片描述
最终发现是通过二级缓存实际上是通过map来储存数据的,key值为statementId+offset+limit+sql+paramValueList+environmentId这些组成,value就是取出的数据,如果从map当中取到数据就直接返回了。我们是没有取到,继续执行到BaseExecutor

请添加图片描述
可以看到这里还有是先去一个map里面取数据,没有取到才会真正去数据库里面查询,这个map就是一级缓存,一级缓存是默认打开的,当数据库查询完毕后,会清空一级缓存,然后会在这里保存一份最新数据请添加图片描述
这里证明了确实是储存一份在一级缓存,最后调用默认的执行器SimpleExecutor来取数据库当中数据
请添加图片描述
里面就是只有jdbc来取数据的,到这里就基本上结束了,当然其中肯定还有一些处理结果集的操作,自己有兴趣自己看吧,没什么特殊的,还记得之前储存的别名映射数据吗,正好接下来使用到了这些数据,最后上一张图总结一下请添加图片描述

2.update方法的执行

和上面实际上是一个流程,但是不同的是query方法是要储存数据到一二级缓存,update是要清空一二级缓存

先去CachingExecutor清空二级缓存

请添加图片描述
update方法的flushCache是默认打开的,是因为增删改操作比较危险,可能存在脏读,所以默认需要刷新
请添加图片描述
但是userCache是默认关闭的,方法处理的时候根本不会去走二级缓存请添加图片描述

然后去BaseExecutor清空一级缓存
请添加图片描述
最后去SimpleExecutor执行sql

请添加图片描述
这样就结束了

二. 一二级缓存探讨

1.一级缓存是sqlsession会话级别的,如果不是一个会话执行的sql,那么存储在不同的位置,当前sqlsession接收了一级缓存也释放了。

2.二级缓存是mapper级别的·,缓存的数据是不会受到sqlsession影响的,只会受到sql的参数影响。

3.一二级缓存的key值都是一样组成的statementId+offset+limit+sql+paramValueList+environmentId,一二级缓存如果都打开,查询结果会在两个缓存都存储,但是由于程序执行的顺序,实际上一级缓存是不会得到使用的。

4.一二级缓存的刷新是不会互相影响的,因为是不同的map存储的

5.二级缓存存储的数据如果太多的话,是有一些淘汰的算法的,默认是LRU淘汰算法,即删除使用最少的。

6.一二级缓存的刷新实际上是清空所有的数据,也就是说刷新就是清空

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值