<cache-ref>的作用是让多个Mapper共享同一二级缓存实例,避免重复缓存、节省内存并保证一致性;它引用已配置<cache>的Mapper的缓存对象,要求namespace完全匹配且不能与<cache>共存。

cache-ref 的作用是让多个 Mapper 共用同一个二级缓存实例,避免重复缓存相同数据,节省内存并保证缓存一致性。
cache-ref 的核心用途
它不是新建缓存,而是“引用”另一个已配置 <cache> 的 Mapper 的缓存对象。被引用的 Mapper 必须已声明 <cache>,否则启动会报错。
- 适用于多张表逻辑强关联、常联合查询的场景(如
UserMapper和UserProfileMapper) - 所有引用同一缓存的 Mapper,增删改操作都会触发该缓存整体清空(即共用 flush 行为)
- 缓存 key 的命名仍基于各自 namespace + SQL ID,不会冲突,但底层存储是同一 Cache 实例
配置步骤与写法
只需在需要共享缓存的 Mapper XML 文件中,用 <cache-ref> 替代 <cache>,并指定目标 namespace:
<mapper namespace="com.example.order.OrderMapper">
<cache-ref namespace="com.example.user.UserMapper"/>
<select id="selectOrderWithUser" resultType="OrderVo">
SELECT o.*, u.name FROM orders o JOIN users u ON o.user_id = u.id
</select>
</mapper>
- 确保
com.example.user.UserMapper的 XML 中已定义<cache/>或完整<cache>配置 - namespace 值必须完全匹配,包括包路径和类名,大小写敏感
- 不能同时存在
<cache>和<cache-ref>,否则解析失败
注意事项与常见问题
共享缓存看似简单,但实际使用需警惕副作用:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 只要任意一个引用该缓存的 Mapper 执行了
insert/update/delete,整个共享缓存会被清空(即使操作的是另一张表) - 实体类必须实现
Serializable(若readOnly="false",即默认读写模式) - 不支持跨 MyBatis SqlSessionFactory 实例共享;仅限同一应用内、同一工厂创建的 SqlSession
- 调试时可通过日志开启
org.apache.ibatis.cache级别观察缓存命中/清空行为
什么时候该用 cache-ref 而不是独立 cache
典型适用场景有两类:
- 主子表或宽表拆分:如
ProductMapper和ProductDetailMapper总是一起查,且更新频率一致 - 读多写少+强一致性要求:比如字典类数据分散在多个 Mapper 中(
StatusMapper、TypeMapper),统一由一个缓存管理更安全
如果各 Mapper 数据更新节奏差异大,或存在部分只读、部分高频变更的情况,建议各自配置独立 <cache>,避免互相干扰。

















