专栏精选
引入Mybatis
Mybatis的快速入门
Mybatis的增删改查扩展功能说明
mapper映射的参数和结果
Mybatis复杂类型的结果映射
Mybatis基于注解的结果映射
Mybatis枚举类型处理和类型处理器
再谈动态SQL
文章目录
- 专栏精选
- 摘要
- 引言
- 正文
- 缓存配置项说明
- cacheEnabled
- localCacheScope
- 一级缓存
- 二级缓存
- 总结
摘要
在这篇文章中,我们将进入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中反复进行同一个查询的方式验证一级缓存。
测试代码如下:
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
内部共享查询结果。
刷新一级缓存的方法有两种
- 在两次查询之间进行一次增删改操作
- 通过
SqlSession#clearCache
方法清空缓存
测试清空缓存
@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
中查询同一内容的方式验证二级缓存是否生效。测试代码为:
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❗版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页