mybatis二级缓存需同时满足三个条件才生效:全局cacheenabled=true、mapper级声明或@cachenamespace、实体类实现serializable接口;缺一不可,否则缓存不生效或运行报错。

MyBatis 二级缓存不是“开一个开关”就生效的,必须同时满足全局启用 + Mapper 级别显式声明,二者缺一不可。
全局开关:确保 cacheEnabled = true
这是总闸门。即使每个 Mapper 都配了缓存,只要这个关了,二级缓存完全不工作。
- 在 mybatis-config.xml 的
<settings></settings>中添加:<setting name="cacheEnabled" value="true"></setting> - Spring Boot 项目中,推荐在 application.yml 里配置:
mybatis:<br> configuration:<br> cache-enabled: true
- 注意:虽然官方默认值是
true,但很多团队会在配置中显式设为false用于调试或禁用,上线前务必检查是否被覆盖。
Mapper 级别:XML 或注解方式启用
只开全局不够,每个需要缓存的 Mapper 必须单独“申请”使用二级缓存,作用域是该 Mapper 的 namespace。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- XML 方式(最常用、最清晰):在对应
Mapper.xml的<mapper></mapper>标签下添加:<cache></cache>(最简写法)
或带参数的完整写法:<cache eviction="LRU" flushinterval="60000" size="1024" readonly></cache> - 注解方式(适用于纯注解开发):在 Mapper 接口上加
@CacheNamespace注解:@Mapper<br>public interface UserMapper { ... }
注意:接口需有@Mapper或被@MapperScan扫描到,且@CacheNamespace必须直接标注在接口上。
实体类必须实现 Serializable
这不是可选项,而是运行前提。二级缓存底层涉及对象跨 SqlSession 甚至跨线程复用,MyBatis 默认使用基于 HashMap 的缓存实现,但一旦启用定时刷新(flushInterval)、集成外部缓存(如 Redis),或未来升级,就会触发序列化 —— 此时若 POJO 没实现 Serializable,直接抛 NotSerializableException。
- 所有可能作为
select返回结果的实体类,都应声明:public class User implements Serializable { ... } - 建议手动指定
serialVersionUID,例如:private static final long serialVersionUID = 1L;
避免因字段增减导致反序列化失败。 - 若用 Lombok,
@Data不自动实现Serializable,需显式补上:@Data<br>public class User implements Serializable { ... }
验证是否真正生效的小技巧
光配对不等于跑通。常见“看似配了却没缓存”的原因:
- 第一次查询走 SQL,第二次没走 SQL → 缓存生效(一级缓存也可能干扰判断,建议用两个不同 SqlSession 测试)
- 始终走 SQL → 先查
cacheEnabled是否为true;再确认 Mapper XML 里有没有<cache></cache>或接口有没有@CacheNamespace - 更新后旧数据还在 → 这是正常行为:MyBatis 对同一 namespace 下任意
insert/update/delete会清空整个该 namespace 的二级缓存,无需额外配置
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










