MyBatis 缓存机制复习及项目中的应用经历

背景

想起前两年工作中因为二级缓存默认开启导致的问题,完整的看了一个介绍 MyBatis 缓存机制的视频《MyBatis 缓存基础知识讲解》。

总计知识点:

  • 缓存的类型及开关
  • 这是个形同虚设的功能,线上环境应该禁用缓存

MyBatis 缓存分类

MyBasit 缓存类型如下:

  1. 一级缓存:SqlSession 级别的缓存,每个 SqlSession 对象维护一个缓存集合,多个 SqlSession 对象之间缓存不共享。
  2. 二级缓存:Mapper 级别的缓存,多个 SqlSession 访问相同 Mapper 对象的时候,共享该 Mapper 的缓存。
  3. 项目中的 SqlSession 是单例,还是多例?

一级缓存原理

MyBatis 缓存机制复习及项目中的应用经历_第1张图片

  1. SQL 缓存的结构:sql ID + 参数,还是 SQL 语句?
  2. 缓存的结果类型:直接是游标,还是 Java 结果集合?
  3. 缓存的刷新,执行 增/删/该 方法之后都会刷新缓存。

二级缓存原理

MyBatis 缓存机制复习及项目中的应用经历_第2张图片
相关知识:
1、二级缓存的数据存储介质多种,所以实体类需要实现序列化接口。
2、二级缓存与 SqlSession 无关。
3、MyBatisPlus 二级缓存默认是开启的

Mybatis 禁用缓存配置

首先,MyBatis 没有提供全局的一级缓存的关闭配置,需要在每个 Mapper 的 sql 语句中配置 flushCache=true 禁用一级缓存,例如:

<select id="getUserInfo" flushCache="true" parameterType="int" resultType="xx.UserInfo" >
select xx
</select>

其次,MyBatis-Plus 提供了二级缓存的开关配置 cache-enabled ,默认开启:

mybatis-plus:
  mapper-locations: classpath*:/mapper/${spring.datasource.type}/*.xml,classpath*:/mapper/public/*.xml
  #实体扫描,多个package用逗号或者分号分隔
  type-aliases-package: com.xx.*.entity
  configuration:
    # 开启驼峰命名规则自动转换
    map-underscore-to-camel-case: true
    #注意:单引号,解决 Oracle参数为null时1111异常
    jdbc-type-for-null: 'null' 
    # 本模块依赖其他模块操作数据库的数据,所以禁止缓存
    cache-enabled: false

以前参与的一个项目中,有两个模块是相互依赖的,一个模块负责数据管理,另一个模块查询它的数据,使用数据库操作框架是 MyBatisPlus。

出现过一个问题,就是另一个模块修改了数据后,另一个模块监控到数据没有发生变化,后来想到是框架缓存的问题,cache-enabled: false 加上该配置就正确了。

总结

线上环境,应该关闭 MyBatis 的缓存:一级缓存在分布式环境中,容易导致脏数据;二级缓存是基于 namespace 的,对于涉及到多表关联的语句时,容易因为脏数据而得不到正确数据。

既然这个功能这么鸡肋,为什么当初要设计它呢?

你可能感兴趣的:(mybatis,缓存,spring)