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

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

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

小小少年_   2022-11-22 我要评论

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

结论

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

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

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

源码

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

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

一级缓存

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

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

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
    org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
        org.apache.ibatis.session.Configuration#newExecutor()

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

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

二级缓存

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

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

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

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

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

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

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

这个方法中,会给currentCache赋值

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

org.apache.ibatis.builder.xml.XMLMapperBuilder#configurationElement
    org.apache.ibatis.builder.xml.XMLMapperBuilder#cacheElement
        org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache

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

所以,我们发现

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

所以,我们说二级缓存是namespace级别的

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

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们