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

 更新时间:2022年11月21日 09:52:16   作者:小小少年_  
这篇文章主要介绍了mybatis一级缓存和二级缓存的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

我们通常说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级别的

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

相关文章

  • 如何使用JaCoCo分析java单元测试覆盖率

    如何使用JaCoCo分析java单元测试覆盖率

    在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至,用代码覆盖率来考核测试任务完成情况,比如,代码覆盖率必须达到80%或 90%。于是乎,测试人员费尽心思设计案例覆盖代码。下面我们来学习一下吧
    2019-06-06
  • MyBatis中使用分页插件PageHelper实现分页功能

    MyBatis中使用分页插件PageHelper实现分页功能

    分页是经常使用的功能,本文主要介绍了Mybatis中处理特殊SQL处理逻辑,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • Java由浅入深细数数组的操作上

    Java由浅入深细数数组的操作上

    数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。Java 语言中提供的数组是用来存储固定大小的同类型元素
    2022-04-04
  • java中的数组初始化赋初值方式

    java中的数组初始化赋初值方式

    这篇文章主要介绍了java中的数组初始化赋初值方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Spring Boot使用Druid和监控配置方法

    Spring Boot使用Druid和监控配置方法

    Druid是Java语言中最好的数据库连接池,并且能够提供强大的监控和扩展功能。下面来说明如何在 Spring Boot 中配置使用Druid
    2017-04-04
  • Spring注解@Transactional失效的场景分析

    Spring注解@Transactional失效的场景分析

    在使用Spring中事务注解@Transactional时会存在几种场景下该注解失效,即不能按照预期封装成一个事务操作,于是本文文将对该注解进行学习并对相关失效场景进行分析,需要的朋友可以参考下
    2023-07-07
  • Spring获取当前类在容器中的beanname实现思路

    Spring获取当前类在容器中的beanname实现思路

    这篇文章主要介绍了Spring获取当前类在容器中的beanname,实现思路只需继承BeanNameAware接口,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • java json与map互相转换的示例

    java json与map互相转换的示例

    这篇文章主要介绍了java json与map互相转换的示例,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-10-10
  • 使用反射方式获取JPA Entity的属性和值

    使用反射方式获取JPA Entity的属性和值

    这篇文章主要介绍了使用反射方式获取JPA Entity的属性和值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java线程池高频面试题总结

    Java线程池高频面试题总结

    在进程和线程的相关面试题中还有一部分是关于多线程和线程池的,也是在这一部分中比较常考察的内容。本篇文章就带你了解一下,希望能给你带来帮助
    2021-08-08

最新评论