mybatis一级缓存和二级缓存区别点

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

结论

先说结论吧,一级缓存之所以说是sqlSession级别的,是因为一级缓存的数据是存放在了sqlSession的一个内部属性中,所以,每次openSession()开启一个sqlSession之后,一级缓存就会失效
二级缓存之所以可以跨sqlSession,是因为二级缓存的数据,是存放在mappedStatement对象中的一个内部属性中,这里说的内部属性其实不太准确,但是先忽略,后面会详细解释
我们知道,mybatis在启动的时候,会解析全局配置文件,会把mapper.xml文件中的一个个sql片段,解析成一个个mappedStatement对象,所以,这里二级缓存自然也就是namespace级别的

源码

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

mybatis一级缓存和二级缓存区别点_第1张图片

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

一级缓存

mybatis一级缓存和二级缓存区别点_第2张图片
这里是一级缓存的处理,会发现,这里是从localCache中根据key获取value的,换而言之,这里的localCache大概率就是我们所谓的一级缓存了,我们看下localCache是在哪里赋值的

mybatis一级缓存和二级缓存区别点_第3张图片
可以看到,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级别的
mybatis一级缓存和二级缓存区别点_第4张图片

二级缓存

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

mybatis一级缓存和二级缓存区别点_第5张图片
二级缓存是从这里的tcm这个对象中来获取的,但是实际上,我们调到tcm.getObject()方法中,会发现实际上是从入参的cache来获取的,所以我们需要看下这里入参的cache是从哪里获取到的
可以看到这个方法的第一行,是从MappedStatement对象中获取到的
mybatis一级缓存和二级缓存区别点_第6张图片
可以看到,mappedStatement对象是从configuration对象中获取到,所以我们要看下configuration的mappedStatement对象是什么时候赋值的

org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement()
mybatis一级缓存和二级缓存区别点_第7张图片
在这个方法中,可以看到,最终会把statement对象设置的configuration中,同时需要注意的是,我们用到的cache对象是从currentCache来的,所以我们需要关注,currentCache是从哪里来的?

在同类中,org.apache.ibatis.builder.MapperBuilderAssistant#useNewCache
这个方法中,会给currentCache赋值
mybatis一级缓存和二级缓存区别点_第8张图片
如果看过前面两篇关于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一级缓存和二级缓存区别点_第9张图片
截图中的这个方法是解析一个mapper.xml的逻辑
mybatis一级缓存和二级缓存区别点_第10张图片
所以,我们发现

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

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

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