Mybatis缓存原理深入分析

蹲厕所的熊 转载请注明原创出处,谢谢!

Mybatis中的缓存原理(不结合spring)

Mybatis中有一级缓存和二级缓存,默认情况下一级缓存是开启的,而且是不能关闭的。一级缓存是指SqlSession级别的缓存,当在同一个SqlSession中进行相同的SQL语句查询时,第二次以后的查询不会从数据库查询,而是直接从缓存中获取,一级缓存最多缓存1024条SQL。二级缓存是指可以跨SqlSession的缓存。 我们可以通过一张图来了解什么是一级缓存和二级缓存

一级缓存

一级缓存是默认启用的,在BaseExecutor的query()方法中实现,底层默认使用的是PerpetualCache实现,PerpetualCache采用HashMap存储数据。一级缓存会在进行增、删、改操作时进行清除。

可以看到上面的查询方法先是看有没有flushCache="true",有就刷新一级缓存,没有的话先去从一级缓存取数据,如果一级缓存里没有结果,调用 方法,从数据库查询结果并返回。

一级缓存的范围有 和 两种,默认是 ,如果我们不需要使用一级缓存,那么我们可以把一级缓存的范围指定为STATEMENT,这样每次执行完一个Mapper语句后都会将一级缓存清除。如果需要更改一级缓存的范围,请在Mybatis的配置文件中,在下通过localCacheScope指定。

我们发现同一个SqlSession的情况下会清除一级缓存,但是不同的SqlSession之间会出现脏数据问题,必须自己手动指定flush。

结论:一级缓存默认存在,不想使用有两种方法关闭。

指定flushCache="true"

二级缓存

mybatis默认Configuration中是启用二级缓存的,可以通过改变配置 来不走二级缓存。

默认二级缓存使用CachingExecutor来分发执行sql,但是要想真正启用二级缓存,还得在xml中指定 ,这样才会真正生效,每个sql标签默认有个属性useCache,默认是true,如果单独某个或某几个sql不想使用二级缓存,可以指定useCache="false"。

的具体使用如下:

接下来我们来看看二级缓存的实现:

小结:

二级缓存开启需要指定

不使用二级缓存类CachingExecutor:

查询标签默认属性 flushCache="false" 和 useCache="true"

其他标签默认属性 flushCache="true" 和 useCache="false"

先走二级缓存再走一级缓存。

Mybatis在spring中的缓存

在之前的文章中,我们说到了Spring中sqlSession是如何运作的,不懂的可以复习一遍。

上面我们针对mybatis自身的缓存做了讲解,下面我们直接看 来看看spring中执行statement时对缓存是如何处理的。下面分两种情况,一种是在spring中没有开启事务的查询,另外一种是开启事务的查询。

没有开启事务

先来看一波涉及到的相关源码

源码中都有注释解释了每一步的操作,有以下几步:

通过 新建一个sqlSession。

执行sqlSession的查询方法,默认放入缓存中。

执行 清除缓存。

调用 方法做资源处理操作

我们可以发现,在spring中不开启事务的情况下,查询是怎么都不会有缓存的!!!

开启了事务

再来看一波涉及到的相关源码,和上面的做一下对比

源码中都有注释解释了每一步的操作,每一次的select statement都有以下几步:

开启事务后,第一次通过 新建一个sqlSession。之后的所有查询操作都会复用之前的sqlSession。也就是session共享。

执行sqlSession的查询方法,默认放入缓存中。

调用 方法进行引用次数-1的操作。

在事务结束后,还会走到mybatis注册的 类的方法中去,来看看它都做了什么

我们来总结一下它都做了什么

的时候调用了sqlSession的commit操作,清除缓存。

的时候调用 方法做资源处理操作。

总结

通过代码可以看出在Spring中每次都会清空一级缓存,这也是spring中一级缓存失效的主要原因。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180604G09E5G00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动