开发者

mybatis一级缓存和二级缓存的区别及说明

开发者 https://www.devze.com 2022-11-28 15:08 出处:网络 作者: 小小少年_
目录结论源码一级缓存二级缓存我们通常说mybatis中一级缓存是sqlSession级别的,二级缓存是namespace级别的,这篇笔记主要来记录下这么说的原理结论先说结论吧,一级缓存之所以说是sql...
目录
  • 结论
  • 源码
  • 一级缓存
  • 二级缓存

我们通常说myBATis中一级缓存是sqlSession级别的,二级缓存是namespace级别的,这篇笔记主要来记录下这么说的原理

结论

先说结论吧,一级缓存之所以说是sqlSession级别的,是因为一级缓存的数据是存放在了sqlSession的一个内部属性中,所以,每次openSession()开启一个sqlSession之后,一级缓存就会失效

二级缓存之所以可以跨sqlSession,是因为二级缓存的数据,是存放在mappedStatement对象中的一个内部属性中,这里说的内部属性其实不太准确,但是先忽略,后面会详细解释

我们知道,mybatis在启动的时候,会解析全局配置文件,会把mapper.XML文件中的一个个sql片段,解析成一个个mappedStatement对象,所以,这里二级缓存自然也就是namespace级别的

源码

在mybatisAjebdzJKCF源码中,CachingExecutor是二级缓存的处理类,BaseExecutor是一级缓存的处理类

mybatis一级缓存和二级缓存的区别及说明

我们先来看一级缓存的处理

一级缓存

mybatis一级缓存和二级缓存的区别及说明

这里是一级缓存的处理,会发现,这里是从localCache中根据key获取value的,换而言之,这里的localCache大概率就是我们所谓的一级缓存了,我们看下localCache是在哪里赋值的

mybatis一级缓存和二级缓存的区别及说明

可以看到,localCache是在BaseExecutor的构造函数中,每次new 出来的,所以,这里我们可以知道,只要new 一个BaseExecutor对象,就编程会有一个localCache,那对应的一js级缓存就不一样,我们再看下,在正常的sql执行过程中,BaseExecutor是在什么时候初始化的

org.apache.ibatis.session.defaults.DefpythonaultSqlSessionFactory#openSession()

    org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource

        org.apache.ibatis.session.Configuration#newExecutor()

这里可以看到,在通过openSession()初始化sqlSession对象的时候,就会初始化一个executor对象

所以,我们说一级缓存是executor级别的

mybatis一级缓存和二级缓存的区别及说明

二级缓存

我们接着来看二级缓存的逻辑

mybatis一级缓存和二级缓存的区别及说明

二级缓存是从这里的tcm这个对象中来获取的,但是实际上,我们调到tcm.getObject()方法中,会发现实际上是从入参的cache来获取的,所以我们需要看下这里入参的cache是从哪里获取到的

可以看到这个方法的第一行,是从MappedStatement对象中获取到的

mybatis一级缓存和二级缓存的区别及说明

可以看到,mappedStatement对象是从configuration对象中获取到,所以我们要看下configuration的mappedStatement对象是什么时候赋值的

org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement()

mybatis一级缓存和二级缓存的区别及说明

在这个方法中,可以看到,最终会把s编程客栈tatement对象设置的configuration中,同时需要注意的是,我们用到的cache对象是从currentCache来的,所以我们需要关注,currentCache是从哪里来的?

在同类中,org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache

这个方法中,会给currentCache赋值

mybatis一级缓存和二级缓存的区别及说明

如果看过前面两篇关于mybatis源码解析博客的,应该会比较清楚,这里的useNewCache()方法,就是在解析mapper.xml文件中的节点时,调用的

org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement

    org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement

        org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache

mybatis一级缓存和二级缓存的区别及说明

截图中的这个方法是解析一个mapper.xml的逻辑

mybatis一级缓存和二级缓存的区别及说明

所以,我们发现

在解析mapper.xml文件的时候,会解析配置的节点,在解析这个节点的时候,会初始化一个cache对象,这个cache对象,会赋值给currentCache然后继续解析一个个sql片段,这一个mapper.xml文件中,无论有多少个sql,这里的currentCache都是一样的二级缓存在使用的时候,会从mappedStatement对象中获取currentCache,如果currentCache不为null,就表示需要使用二级缓存然后从currentCache,根据key获取value这里需要知道的是:这里的currentCache,也是对PerpetualCache的包装,以前文章有介绍过,这次不做过多的解读

所以,我们说二级缓存是namespace级别开发者_Js入门

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

0

精彩评论

暂无评论...
验证码 换一张
取 消