MyBatis缓存核心是一级缓存默认自动生效、二级缓存需手动配置,查询时按“二级缓存→一级缓存→数据库”优先级执行;一级缓存作用于单个SqlSession内相同查询,二级缓存跨SqlSession共享但要求Mapper开启且实体类实现Serializable。

MyBatis 用缓存防重复查库,核心是靠**一级缓存自动生效 + 二级缓存按需开启**,不是“手动存取”,而是框架在查询流程中自动拦截、命中、写入。关键在于理解它怎么走、什么时候生效、哪些操作会让它失效。
一级缓存:同一请求内自动挡(默认就起作用)
只要没关 SqlSession,同一个会话里查相同 SQL 和参数,第二次起直接返回内存对象,不发 SQL。
- 不用配、不能关,开箱即用
- 适用场景:一次 HTTP 请求里多次查同一条数据(比如先查用户,再查该用户的权限,再查其角色)
- 注意:不同请求 → 不同 SqlSession → 缓存不共享,所以它只管“单次请求内的省查”
二级缓存:跨请求共享数据(需要三步手动配)
想让多个请求共用一份缓存(比如所有用户查 id=1 的商品都从缓存拿),就得开二级缓存。必须同时满足:
- 全局开关打开:
(mybatis-config.xml,默认就是 true) - Mapper 文件里声明:
或@CacheNamespace注解 - 查询返回的实体类实现
Serializable接口(因为要序列化存到共享缓存里)
缓存不是万能的:这些操作会让它清空
MyBatis 主动保一致,一有写操作就清缓存,避免读到旧数据:
- 执行了
INSERT、UPDATE、DELETE语句(哪怕改的是另一张表) - 调用了
sqlSession.commit()、sqlSession.rollback()或sqlSession.close() - 显式调用
sqlSession.clearCache()
查数据时的实际路径(优先级从高到低)
每次 select 执行,MyBatis 按顺序检查:
- 先看二级缓存(如果开了)→ 命中就返回
- 没命中,再看一级缓存(当前 SqlSession 里有没有)→ 命中就返回
- 两级都没命中,才真正查数据库 → 结果同时写进一级缓存,提交后还会刷进二级缓存(如果开了)











