Mybatis 缓存机制
TIP
MyBatis 内置了二级缓存机制,可以有效减少数据库查询次数,提升系统性能。
一级缓存(SqlSession 级别)
默认开启,同一个 SqlSession 中共享缓存:
java
// 同一个 SqlSession 中查询两次
try (SqlSession session = factory.openSession()) {
UserMapper mapper = session.getMapper(UserMapper.class);
User user1 = mapper.selectById(1L); // 查数据库
User user2 = mapper.selectById(1L); // 走缓存,不查数据库
System.out.println(user1 == user2); // true(同一个对象)
}一级缓存失效场景
java
// 1. 执行了 DML 操作(插入、更新、删除)
mapper.selectById(1L); // 查数据库
mapper.updateById(user); // DML 操作,清空缓存
mapper.selectById(1L); // 重新查数据库
// 2. 调用了 clearCache()
session.clearCache();
// 3. 不同 SqlSession二级缓存(Mapper 级别)
跨 SqlSession 共享,需手动开启:
xml
<!-- mybatis-config.xml 开启二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- Mapper XML 中开启 -->
<mapper namespace="com.example.mapper.UserMapper">
<cache
eviction="LRU"
flushInterval="60000"
size="512"
readOnly="false"/>
</mapper>缓存属性
| 属性 | 说明 | 默认值 |
|---|---|---|
| eviction | 淘汰策略(LRU/FIFO/SOFT/WEAK) | LRU |
| flushInterval | 刷新间隔(毫秒) | 不刷新 |
| size | 缓存对象数量 | 1024 |
| readOnly | 是否只读 | false |
使用要求
java
// 实体类必须实现 Serializable
public class User implements Serializable {
private static final long serialVersionUID = 1L;
// ...
}自定义缓存
java
// 实现 Cache 接口,可以集成 Redis
public class RedisCache implements Cache {
private String id;
private RedisTemplate redisTemplate;
public RedisCache(String id) {
this.id = id;
}
@Override
public void putObject(Object key, Object value) {
redisTemplate.opsForValue().set(key, value, 60, TimeUnit.MINUTES);
}
@Override
public Object getObject(Object key) {
return redisTemplate.opsForValue().get(key);
}
@Override
public Object removeObject(Object key) {
return redisTemplate.delete(key);
}
@Override
public void clear() {
// 清空缓存
}
@Override
public int getSize() {
return 0;
}
}
// 在 Mapper XML 中使用
// <cache type="com.example.cache.RedisCache"/>TIP
- 一级缓存默认开启且无法关闭
- 二级缓存适用于读多写少的场景
- 需要序列化的实体类注意修改后及时清理缓存