Mybatis行为配置之Ⅰ—缓存

专栏精选

引入Mybatis

Mybatis的快速入门

Mybatis的增删改查扩展功能说明

mapper映射的参数和结果

Mybatis复杂类型的结果映射

Mybatis基于注解的结果映射

Mybatis枚举类型处理和类型处理器

再谈动态SQL

Mybatis配置入门

Mybatis行为配置之Ⅰ---缓存

Mybatis行为配置之Ⅱ---结果相关配置项说明

Mybatis行为配置之Ⅲ---其他行为配置项说明

Mybatis行为配置之Ⅳ---日志

Mybatis整合Spring详解

Mybatis插件入门

Mybatis专栏代码资源

文章目录

摘要

在这篇文章中,我们将进入Mybatis行为配置的世界,了解Mybatis一二级缓存的基本方法,其中的很多观点或内容都能在一定程度上让我们的开发之旅更加轻松方便,这是一个菜鸟提升技术能力,老鸟巩固基础知识的好机会。准备好开启今天的神奇之旅了吗?

引言

大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。欢迎来到我的频道,这里汇聚了汇集编程技巧、代码示例和技术教程,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 🙆,期待在这里与你共同度过美好的时光🕹️。今天要和大家分享的内容是Mybatis行为配置之缓存。做好准备,Let's go🚎🚀

正文

在Mybatis 的配置文件中 <setting>标签用于配置Mybatis项目执行过程中的行为,这些行为配置项每一个都对应 Configuration类中的一个属性, Configuration类也为这些属性提供了setter方法,除了使用配置文件之外,我们还可以通过调用这些方法来完成相应的配置。当然,这些行为配置项Mybatis大都有默认的配置,默认配置在Mybatis的源码中 org.apache.ibatis.builder.xml.XMLConfigBuilder类的 settingsElement方法中定义,可自行查看

缓存配置项说明

cacheEnabled

备注:是否开启二级缓存

默认值:true

建议值:false

建议原因:

mybatis缓存包括一级缓存和二级缓存,一级缓存是不能关闭的(可以通过配置修改作用域),二级缓存可以通过此配置关闭。关于一二级缓存的详细内容,见[[Mybatis缓存]]

在集群/微服务环境下,其他服务修改了同一个文件对当前微服务是不可见的,在这种情况下,数据库里的真实数据已经更新了,但当前服务的缓存仍然在生效中,会读取到脏数据。

localCacheScope

备注:设置一级缓存作用域

默认值:SESSION

建议值:STATEMENT

建议原因:微服务环境下可以防止读取到脏数据。

下面介绍一二级缓存的详细说明

一级缓存

mybatis的一级缓存提供SqlSession级别的查询结果缓存,也就是说在同一个SqlSession中,如果没有进行过增删改操作,相同条件的sql查询会通过一级缓存查询结果,而不用反复通过数据库执行sql。

一级缓存是全局开启的,只能通过localCacheScope这个配置修改一级缓存的作用域,可选的配置包括:

可选项 是否默认值 说明
SESSION yes 缓存作用在session级别,同一个SqlSession中共享
STATEMENT no 缓存作用在一个查询级别

可以通过在一个sqlSession中反复进行同一个查询的方式验证一级缓存。

测试代码如下:

java 复制代码
public class EnvConfigTest {  
    private SqlSessionFactory sqlSessionFactory;  
  
    @Before  
    public void before() {  
        try (InputStream input = EnvConfigTest.class.getResourceAsStream("/mybatis-config.xml")) {  
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();  
            sqlSessionFactory = builder.build(input);  
        } catch (IOException e) {  
            throw new RuntimeException(e);  
        }  
    }
    
	@Test  
	public void testSessionCache(){  
	    SqlSession session = this.sqlSessionFactory.openSession();  
	    ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);  
	    AppTestEntity e1 = mapper.queryById(2L);  
	  
	    AppTestEntity e2 = mapper.queryById(2L);  
	  
	    System.out.println("boolean(e1=e2) is "+(e1==e2));  
	    session.close();  
	}
}

设置<setting name="localCacheScope" value="SESSION"/>时的打印结果为:

boolean(e1=e2) is true

设置<setting name="localCacheScope" value="STATEMENT"/> 时的打印结果为:

boolean(e1=e2) is false

可以看出,STATEMENT作用域的作用范围就是一次sql查询,也就时变相的关闭了Mybatis的一级缓存。而SESSION作用域会在同一个 sqlSession内部共享查询结果。

刷新一级缓存的方法有两种

  1. 在两次查询之间进行一次增删改操作
  2. 通过 SqlSession#clearCache 方法清空缓存

测试清空缓存

java 复制代码
    @Test  
    public void testSessionCache(){  
        SqlSession session = this.sqlSessionFactory.openSession();  
        ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);  
        AppTestEntity e1 = mapper.queryById(2L);  
  
        session.clearCache();  
        AppTestEntity e2 = mapper.queryById(2L);  
  
        System.out.println("boolean(e1=e2) is "+(e1==e2));  
        session.close();  
    }

配置<setting name="localCacheScope" value="SESSION"/>时的打印结果为:

boolean(e1=e2) is false

二级缓存

Mybatis的二级缓存可是实现在多个SqlSession中共享,默认是开启的,可以通过 <setting name="cacheEnabled" value="false"/>这个配置项关闭。二级缓存的作用域是一个namespace,即mapper映射文件中的namespace。

可以通过在两个 SqlSession 中查询同一内容的方式验证二级缓存是否生效。测试代码为:

java 复制代码
public class EnvConfigTest {  
    private SqlSessionFactory sqlSessionFactory;
	//省略@Before

	@Test  
    public void testCacheFirst() {  
        SqlSession session1 = this.sqlSessionFactory.openSession();  
        ApplicationRepository mapper1 = session1.getMapper(ApplicationRepository.class);  
        SqlSession session2 = this.sqlSessionFactory.openSession();  
        ApplicationRepository mapper2 = session2.getMapper(ApplicationRepository.class);  
  
        System.out.println("==session1查询==");  
        AppTestEntity e1 = mapper1.queryById(1L);  
		//提交事务,使二级缓存生效
        session1.commit();  
  
        System.out.println("==session2查询==");  
        AppTestEntity e2 = mapper2.queryById(1L);  
        System.out.println("boolean(session1_e1=session2_e2) is "+(e1==e2));  
  
        session1.close();  
        session2.close();  
    }
}

配置 <setting name="cacheEnabled" value="false"/>时的效果

==session1查询==
==session2查询==
boolean(session1_e1=session2_e2) is false

配置 <setting name="cacheEnabled" value="true"/>或不配置时的效果

==session1查询==
==session2查询==
boolean(session1_e1=session2_e2) is true

这里需要注意一点,要使二级缓存生效,需要在查询条件后提交事务(或者通过框架控制事务执行,如Spring中的@Transicational注解),如果没有提交事务也不会走二级缓存。如果注释掉测试代码中的 session1.commit();一行,打印结果为:

==session1查询==
==session2查询==
boolean(session1_e1=session2_e2) is false

总结

在这片文章中我们介绍了Mybatis中缓存的配置,以及如何确定一个查询是否走了缓存。Mybatis的缓存分为一级缓存和二级缓存,一二级缓存都是默认开启的,其中二级缓存可以通过配置关闭,而一级缓存是不能关闭的,只能通过配置修改一级缓存的作用域。


📩 联系方式

邮箱:qijilaoli@foxmail.com

❗版权声明

本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页

相关推荐
栗子~~1 小时前
集成 jacoco 插件,查看单元测试覆盖率
缓存·单元测试·log4j
张铁铁是个小胖子10 小时前
MyBatis学习
java·学习·mybatis
Hello.Reader10 小时前
Redis热点数据管理全解析:从MySQL同步到高效缓存的完整解决方案
redis·mysql·缓存
麦香--老农11 小时前
windows 钉钉缓存路径不能修改 默认C盘解决方案
缓存·钉钉
C++忠实粉丝12 小时前
Redis 介绍和安装
数据库·redis·缓存
丰云12 小时前
一个简单封装的的nodejs缓存对象
缓存·node.js
Oneforlove_twoforjob12 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
泰伦闲鱼12 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
ClouGence12 小时前
Redis 到 Redis 数据迁移同步
数据库·redis·缓存
hanbarger14 小时前
mybatis框架——缓存,分页
java·spring·mybatis