MyBatis缓存机制:一级缓存、二级缓存、PerpetualCache、namespace缓存详解
MyBatis缓存机制详解
缓存概述
MyBatis提供了两级缓存机制来提升查询性能,减少数据库访问次数。
一级缓存
基本特性
一级缓存是SqlSession级别的缓存,默认开启且无法关闭。
核心特点:
作用域:SqlSession内部
实现:PerpetualCache(基于HashMap)
生命周期:与SqlSession相同
清空时机:执行update/delete/insert或手动清空
工作流程
使用示例
@Testpublic void testFirstLevelCache() { SqlSession session = sqlSessionFactory.openSession(); try { ProductMapper mapper = session.getMapper(ProductMapper.class); // 第一次查询 - 访问数据库 Product product1 = mapper.findById(1001L); System.out.println("First query: " + product1); // 第二次查询 - 命中一级缓存,不访问数据库 Product product2 = mapper.findById(1001L); System.out.println("Second query: " + product2); // 两次查询返回同一个对象 assert product1 == product2; // 执行更新操作 - 清空一级缓存 Product updateProduct = new Product(); updateProduct.setId(1002L); updateProduct.setPrice(new BigDecimal("999")); mapper.updateProduct(updateProduct); // 再次查询 - 重新访问数据库 Product product3 = mapper.findById(1001L); System.out.println("Third query: " + product3); } finally { session.close(); }}
源码实现
public class PerpetualCache implements Cache { private final String id; private final Map
缓存Key生成
一级缓存的Key由多个因素组成:
public class CacheKey implements Cloneable, Serializable { private static final int DEFAULT_MULTIPLIER = 37; private static final int DEFAULT_HASHCODE = 17; private int multiplier; private int hashcode; private long checksum; private int count; private List
CacheKey包含以下信息:
MappedStatement的id
RowBounds的offset和limit
SQL语句
参数值
Environment的id
一级缓存的问题
1. 作用域限制
// 问题场景:不同SqlSession无法共享缓存SqlSession session1 = sqlSessionFactory.openSession();SqlSession session2 = sqlSessionFactory.openSession();ProductMapper mapper1 = session1.getMapper(ProductMapper.class);ProductMapper mapper2 = session2.getMapper(ProductMapper.class);// session1查询,缓存在session1中Product p1 = mapper1.findById(1001L);// session1更新数据p1.setPrice(new BigDecimal("999"));mapper1.updateProduct(p1);session1.commit();// session2查询 - 仍然返回旧数据(脏数据)Product p2 = mapper2.findById(1001L);
2. 容量无限制
// 一级缓存没有容量限制,可能导致内存溢出for (int i = 0; i < 100000; i++) { mapper.findById((long) i); // 每次查询都缓存}
配置说明
可以通过localCacheScope设置缓存级别:
二级缓存
基本特性
二级缓存是namespace级别的缓存,需要手动开启。
核心特点:
作用域:namespace(Mapper)
跨SqlSession共享
需要手动配置开启
支持多种缓存实现
装饰器模式实现
开启二级缓存
步骤1:全局配置
步骤2:Mapper配置
配置属性说明:
eviction: 缓存回收策略
LRU(默认):最近最少使用
FIFO:先进先出
SOFT:软引用
WEAK:弱引用
flushInterval: 刷新间隔(毫秒)
size: 缓存对象数量(默认1024)
readOnly: 是否只读
true:返回缓存对象的同一实例(性能好,但不安全)
false:返回缓存对象的副本(安全,但性能差)
步骤3:实体类实现Serializable
public class Product implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String name; private BigDecimal price; // ...}
工作流程
装饰器模式实现
MyBatis使用装饰器模式增强缓存功能:
👉 点击解锁全部付费内容
依纷内衣怎么样?深度评测与使用心得