以下是MyBatis缓存配置的完整示例,包含一级缓存、二级缓存、自定义缓存策略等核心场景,并附详细注释和总结表格:
1. 一级缓存(默认开启)
java
// 使用同一SqlSession执行两次查询,自动命中一级缓存
try (SqlSession session = sqlSessionFactory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user1 = mapper.selectById(1); // 第一次查询(数据库)
User user2 = mapper.selectById(1); // 第二次查询(缓存命中)
System.out.println(user1 == user2); // 输出:true
}
2. 二级缓存配置(XML方式)
xml
<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 开启二级缓存 -->
<cache
eviction="FIFO" <!-- 缓存回收策略:先进先出 -->
flushInterval="60000" <!-- 缓存刷新间隔:60秒 -->
size="512" <!-- 缓存最大条目数 -->
readOnly="false"/> <!-- 是否只读(false允许对象修改) -->
<select id="selectById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
3. 二级缓存注解配置
java
// UserMapper.java
@Mapper
@CacheNamespace(
implementation = EhcacheCache.class, // 使用第三方缓存(如Ehcache)
eviction = CacheNamespaceEvictionPolicy.FIFO,
flushInterval = 60000,
size = 512,
readWrite = true
)
public interface UserMapper {
User selectById(Integer id);
}
4. 缓存对象序列化配置
java
// User实体类需要实现Serializable接口
public class User implements Serializable {
private Integer id;
private String name;
private transient Integer age; // transient字段不参与序列化
// 省略getter/setter
}
5. 缓存手动操作示例
java
// 清除指定对象缓存
sqlSession.clearCache(); // 清除一级缓存
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.selectById(1);
sqlSession.commit(); // 触发二级缓存更新
// 清除二级缓存
((org.apache.ibatis.session.Configuration)sqlSession.getConfiguration())
.getCache("com.example.mapper.UserMapper")
.clear();
关键技术点总结表
场景 | 配置方式 | 适用情况 | 核心注释 |
---|---|---|---|
一级缓存 | 默认开启(SqlSession级别) | 单次业务操作内多次查询 | 不需要配置,关闭需调用sqlSession.clearCache() |
二级缓存 | <cache> 标签或@CacheNamespace |
跨SqlSession的全局缓存 | 必须实现Serializable,需在Mapper配置中显式开启 |
缓存回收策略 | eviction="FIFO/LRU/SID" |
控制内存占用 | LRU(最近最少使用)最常用 |
缓存过期 | flushInterval="60000" |
定时刷新缓存 | 毫秒单位,配合数据库数据变更频率设置 |
缓存容量 | size="512" |
控制内存使用 | 根据业务数据量合理设置 |
缓存可写性 | readOnly="false" |
允许修改缓存对象 | readOnly为true时返回对象为不可变副本 |
第三方缓存 | implementation=EhcacheCache |
需要分布式缓存 | 需引入对应依赖并配置缓存实现类 |
6. 核心配置注意事项:
- 序列化要求 :被缓存的对象必须实现
Serializable
接口 - 事务边界:SqlSession关闭或提交(commit)会刷新二级缓存
- 并发控制 :
readOnly="true"
可避免并发修改问题 - 缓存失效:数据更新操作(insert/update/delete)会自动清除相关缓存
- 命名空间:二级缓存按Mapper命名空间隔离,需确保唯一性
7. 性能验证示例
java
// 验证二级缓存跨SqlSession命中
try (SqlSession session1 = sqlSessionFactory.openSession()) {
UserMapper mapper1 = session1.getMapper(UserMapper.class);
User user1 = mapper1.selectById(1); // 数据库查询
}
try (SqlSession session2 = sqlSessionFactory.openSession()) {
UserMapper mapper2 = session2.getMapper(UserMapper.class);
User user2 = mapper2.selectById(1); // 二级缓存命中
System.out.println(user1.equals(user2)); // 输出:true(值相等但对象不同)
}
需要进一步扩展场景(如条件缓存、自定义缓存实现)可补充说明。