蹲厕所的熊 转载请注明原创出处,谢谢!
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中一级缓存失效的主要原因。
领取专属 10元无门槛券
私享最新 技术干货