mybatis-plus: configuration: cache-enabled: true
@CacheNamespace 注解package com.xxx.myProject.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.CacheNamespace;@CacheNamespace
public interface SysUserMapper extends BaseMapper {// 省略
}
// 其它省略
public class SysUser implements Serializable {// 省略
}
,并指定命名空间如果项目中使用 Mapper.xml 写 SQL ,则配置如下, 如果没有,则跳过此步骤。
此处为什么使用
,而不是?如果 使用
,即,则 项目中出现两个key相同的缓存 ,即 XxxMapper.xml 中的缓存和 XxxMapper.java 中的缓存, 这两个缓存 肯定不会合并,谁覆盖谁呢 ?
实际上,MybatisPlus 内置很多常用方法,另外,开发者还可以在 XxxMapper.java 或者 XxxMapper.xml 自定义SQL, 这两处的SQL 都是 XxxMapper 下方法,对应的缓存 应该合并到一起, 因此应该使用,让 XxxMapper.xml 中的缓存 合并到 XxxMapper.java 的缓存中 。
二级缓存作用于 namespace 针对于多个 sqlSession 共有,对于经常要获取最新数据的不建议使用二级缓存!
MyBatis 二级缓存使用的在某些场景下会出问题,来看一下为什么这么说。
假设,项目有一条 select 语句(已开启了 MyBatis 二级缓存):
select a.col1, a.col2, a.col3, b.col1, b.col2, b.col3
from tableA a, tableB b
where a.id= b.id
对于 tableA 与 tableB 的操作定义在两个Mapper中,分别叫做 MapperA 与 MapperB ,它们属于两个命名空间。
执行下面3个操作:
(1)MapperA 中执行上述 sql 语句查询这6个字段。
(2)tableB 表 更新了 col1 与 col2 两个字段 。
(3)MapperA 再次执行上述sql语句查询这6个字段(前提是没有执行过任何 insert、delete、update操作)。
此时问题就来了,即使第(2)步 tableB 更新了 col1 与 col2 两个字段,第(3)步 MapperA 走二级缓存,查询到的这6个字段依然是原来的这6个字段的值, 没有看到变化后的值。
因为我们从 CacheKey 的3组条件来看,
标签所在的Mapper的Namespace 标签的id属性,RowBounds 的 offset 和 limit 属性,RowBounds 是 MyBatis 用于处理分页的一个类,offset 默认为0,limit默认为Integer.MAX_VALUE ,以及 标签中定义的sql语句。
对于MapperA来说,其中的任何一个条件都没有变化,自然会将原结果返回。
这个问题对于MyBatis的二级缓存来说是一个无解的问题,因此使用MyBatis二级缓存有一个前提:必须保证所有的增删改查都在同一个命名空间下才行。
对于多表联合查询,如果不在同一个命名空间下,则数据容易出现脏读。