mybatis缓存详解

简介: mybatis缓存详解

mybatis的缓存

mybatis的一级缓存是Session级别的缓存。一级缓存的作用域默认是一个SqlSession。Mybatis默认开启一级缓存。

在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并把对象放入缓存中,第二次以后是直接去缓存中取。当执行SQL查询中间发生了事务提交的操作,都会把当前SqlSession的缓存清空。

两条SQL的下列五个值相同,即可以认为是相同的SQL。

StatementId+Offset+Limit+Sql+Params
CacheKey cacheKey = new CacheKey();
//MappedStatement的id
// id 就是Sql语句的所在位置 包名 + 类名 + SQL名称
cacheKey.update(ms.getId());
// offset 就是 0
cacheKey.update(rowBounds.getOffset());
// limit 就是 Integer.MAXVALUE
cacheKey.update(rowBounds.getLimit());
// 具体的SQL语句
cacheKey.update(boundSql.getSql());
//后面是update了sql中带的参数
cacheKey.update(value);
...

如果以上的sqlSession与sql都是同一个,那么在第二次查询的时候就会是一级缓存,而不是执行数据库查询

具体的实现如下

@Test
//  @Transactional
  public void testMybatis2(){
    SqlSession sqlSession = factory.openSession();
    SysQuartzJobLogMapper sysQuartzJobLogMapper1 = sqlSession.getMapper(SysQuartzJobLogMapper.class);
    SysQuartzJobLogMapper sysQuartzJobLogMapper2 = sqlSession.getMapper(SysQuartzJobLogMapper.class);
    List<Map<String, Object>> jobLogsById = sysQuartzJobLogMapper1.getJobLogsById(new Page<>(1, 10), "23dedbb5-af24-11ec-a42d-0894ef72d9c4");
    System.out.println(jobLogsById.size() + "==>" + jobLogsById);
    /*try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }*/
    List<Map<String, Object>> jobLogsById2 = sysQuartzJobLogMapper2.getJobLogsById(new Page<>(1, 10), "23dedbb5-af24-11ec-a42d-0894ef72d9c4");
    System.out.println(jobLogsById2.size() + "==>" + jobLogsById2);
  }

注意⚠️:从截图中可以看出来,打印sql执行只打印了一次,而第二次直接输出结果,说明是直接从缓存中查出来的,这里还需要注意的是使用的sqlSeeion来获取的相关mapper。

如果使用的是springbean的方式来获取mapper

@Test
//  @Transactional
  public void testMybatis2(){
    /*SqlSession sqlSession = factory.openSession();
    SysQuartzJobLogMapper sysQuartzJobLogMapper1 = sqlSession.getMapper(SysQuartzJobLogMapper.class);
    SysQuartzJobLogMapper sysQuartzJobLogMapper2 = sqlSession.getMapper(SysQuartzJobLogMapper.class);*/
    List<Map<String, Object>> jobLogsById = sysQuartzJobLogMapper.getJobLogsById(new Page<>(1, 10), "23dedbb5-af24-11ec-a42d-0894ef72d9c4");
    System.out.println(jobLogsById.size() + "==>" + jobLogsById);
    /*try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }*/
    List<Map<String, Object>> jobLogsById2 = sysQuartzJobLogMapper.getJobLogsById(new Page<>(1, 10), "23dedbb5-af24-11ec-a42d-0894ef72d9c4");
    System.out.println(jobLogsById2.size() + "==>" + jobLogsById2);

注意⚠️:可以从执行结果来看,这里其实用到的是同一个sql,导致mybatis一级缓存失效的原因是两个SqlSession,可以发现这里是创建了两个SqlSession。

然后如果在这个测试类上加入@Transactional注解的时候发现他又可以使用一级缓存了。

原因分析

结论:Spring将MyBatis的DefaultSqlSession类替换成了SqlSessionTemplate。

MyBatis的一级缓存是基于SqlSession来实现的,对应MyBatis中sqlSession接口的默认实现类是DefaultSqlSession,如果执行的SQL相同时,并且使用的是同一个SqlSession对象,那么就会触发对应的缓存机制。

但是在Spring整合MyBatis后,Spring使用MyBatis不再是直接调用MyBatis中的信息,而是通过调用调用mybatis-spring.jar中的类,继而达到间接调用MyBatis的效果。但在mybatis-spring.jar中,引入了一个SqlSessionTemplate类,它和Spring的事务管理器共同配合,创建对应的SqlSession连接。

即在没有添加@Transactional注解的情况下,每调用一次查询SQL,就会通过SqlSessionTemplate去创建sqlSession,即相当于新创建一次连接,故而每次查询在调试结果看来就是一级缓存失效。

除此之外如果是在mysql中操作删除或者更新数据,那么就会造成两次获取到的数据不一致

并且在我看来这个一级缓存是没什么意义的,因为一般不会在同一个方法中会调用某个方法两次。

mybatis的二级缓存,针对的是mapper,或者也可以说是sqlFactory

首先说一下他的配置

在配置文件中加入这句话

mybatis-plus.configuration.cache-enabled=true

然后在你想要开启二级缓存的mapper中加入

<cache/>
相关文章
|
4月前
|
存储 缓存 NoSQL
mybatisplus一二级缓存
MyBatis-Plus 继承并优化了 MyBatis 的一级与二级缓存机制。一级缓存默认开启,作用于 SqlSession,适用于单次会话内的重复查询;二级缓存需手动开启,跨 SqlSession 共享,适合提升多用户并发性能。支持集成 Redis 等外部存储,增强缓存能力。
|
6月前
|
缓存 Java 数据库连接
Mybatis一级缓存详解
Mybatis一级缓存为开发者提供跨数据库操作的一致性保证,有效减轻数据库负担,提高系统性能。在使用过程中,需要结合实际业务场景选择性地启用一级缓存,以充分发挥其优势。同时,开发者需注意其局限性,并做好事务和并发控制,以确保系统的稳定性和数据的一致性。
226 20
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
8月前
|
缓存 Java 数据库连接
Mybatis一级缓存、二级缓存详讲
本文介绍了MyBatis中的查询缓存机制,包括一级缓存和二级缓存。一级缓存基于同一个SqlSession对象,重复查询相同数据时可直接从缓存中获取,减少数据库访问。执行`commit`操作会清空SqlSession缓存。二级缓存作用于同一namespace下的Mapper对象,支持数据共享,需手动开启并实现序列化接口。二级缓存通过将数据存储到硬盘文件中实现持久化,为优化性能,通常在关闭Session时批量写入缓存。文章还说明了缓存的使用场景及注意事项。
300 7
Mybatis一级缓存、二级缓存详讲
|
9月前
|
缓存 Java 数据库连接
十、MyBatis的缓存
十、MyBatis的缓存
194 6
|
10月前
|
缓存 NoSQL Java
Mybatis学习:Mybatis缓存配置
MyBatis缓存配置包括一级缓存(事务级)、二级缓存(应用级)和三级缓存(如Redis,跨JVM)。一级缓存自动启用,二级缓存需在`mybatis-config.xml`中开启并配置映射文件或注解。集成Redis缓存时,需添加依赖、配置Redis参数并在映射文件中指定缓存类型。适用于查询为主的场景,减少增删改操作,适合单表操作且表间关联较少的业务。
202 6
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
11月前
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
449 4
|
11月前
|
缓存 Java 数据库连接
MyBatis缓存机制
MyBatis提供两级缓存机制:一级缓存(Local Cache)默认开启,作用范围为SqlSession,重复查询时直接从缓存读取;二级缓存(Second Level Cache)需手动开启,作用于Mapper级别,支持跨SqlSession共享数据,减少数据库访问,提升性能。
206 1
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
467 5
下一篇
oss云网关配置