spring+mybatis缓存的问题及源码

最近和金业探讨过mybatis缓存的问题,供大家查阅也正好记录下。
文档中分为三个部分:结论理解,mybatis缓存的源码解析,spring+mybaits的整合及对mybatis的代理以及对mybatis缓存的影响
1、结论在这里
【无事务前提,dao每个sql操作都是一个sqlSession实例在进行操作不可能共用一级缓存。在有事务前提下,同个事务内使用一个sqlSession实例所以这个事务内的所有sql会共用一级缓存】
缓存key 按照sql + 参数条件内容等构建。颗粒度很细。
疑问:基本上没命中为什么还要一级缓存呢,因为同一事务内是事务可见的为提高性能这种一级缓存对事务情况非常有用。

2、mybatis缓存
mybatis分为一级缓存和二级缓存。为了防止混淆我们把一级缓存叫为sqlSession级缓存(声明周期和sqlSession的生命周期一致,下面将spring + mybatis整合时会详细说明spring对mybatis sqlSession的代理机制)。
二级缓存叫为mybatis全局缓存生命周期和虚拟机声明周期一致。
(1)全局缓存(二级缓存)
spring+mybatis缓存的问题及源码_第1张图片
图(1.1)
mybatis在创建数据库session的时候通过配置判断,来选择是否使用全局缓存。
spring+mybatis缓存的问题及源码_第2张图片
从两张源码的截图看出,每次创建session用到每个executor实例都是新new出来的,sqlSession的实例也是新new出来的。
spring+mybatis缓存的问题及源码_第3张图片
mybatis全局缓存配置如上图。
(2)sqlSession级缓存(一级缓存)
从SimpleExecutor入手, 他有一个除CachingExecutor外的executor模板类BaseExecutor父类,大多数的基本sql执行功能都在BaseExecutor里封装。
spring+mybatis缓存的问题及源码_第4张图片
从baseExecutor的源码中看出每个executor都持有缓存实例,也就是说这个缓存是和sqlSession一个生命周期的,因为executor的实例和sqlSession的实例的生命周期是一致的(从图(1.1)看出每创建一个sqlSession实例就创建一个executor实例给这个sqlSession)。
spring+mybatis缓存的问题及源码_第5张图片
从图中看出每次执行query都强使用缓存。
spring+mybatis缓存的问题及源码_第6张图片
从图中看出每次commit都会清缓存。也为事务的情况埋下伏笔。
下面会着重说spring + mybatis整合,对缓存的影响和事务也有关哦。

3、spring plugin mybatis
spring提供的sqlSession模板类,为mybatis sqlSession包装成了jdk 动态代理。也就是说在你的dao使用了spring SqlSessionDaoSupport时,在创建这个dao实例bean的时候,spring装入了sqlSessionFactoy,并且为sqlSession生成一个代理对象。当每次dao调用sqlSession实例执行方法操作时,其实使用预先生成好的代理执行,执行源码如下。注:(spring使用把sqlSession代理的方式实现了事务的管理,这里不再引申,spring的事务的处理会单独出新的章节,不过如果对于spring aop 和 spring mybatis 比较理解的话对于理解spring事务的管理比较有帮助 )
spring+mybatis缓存的问题及源码_第7张图片
spring+mybatis缓存的问题及源码_第8张图片
从上两张截图源码中看出每个dao实例会持有一个SqlSessionTemplate,SqlSessionTemplate中持有一个SqlSession的动态代理实例。下面看下这个代理干了什么,也是这部分代码的核心。
spring+mybatis缓存的问题及源码_第9张图片
从图中看出每次调用sqlSession的方法,都会走入这个代理,先会从SqlSessionUtils中获取个session 下面看下spring这个工具类是怎么获取sqlSession这影响一级缓存的生命周期。
spring+mybatis缓存的问题及源码_第10张图片
spring+mybatis缓存的问题及源码_第11张图片
SqlSessionUtils中获取个session源码中看出。如果开启事务则这些所有sqlSession方法的调用都是一个sqlSession.否则调用mybatis sessionFactory创建一个新session,进入了图(1.1)的代码里去了。
spring+mybatis缓存的问题及源码_第12张图片
从以上图中看每次调用这个代理在非事务的情况下都会关闭session 这是会释放这个sqlSession持有的缓存对象。如果在事务范围内将公用sqlSession包括缓存,事务。
结论放在上面。其实个人喜欢通过不断看源码在得出结论,这样会印象深刻。不硬记便于提高和理解。

你可能感兴趣的:(spring,java,源码,mybatis)