您好,登录后才能下订单哦!
# MyBatis中的一级和二级缓存怎么用
## 一、MyBatis缓存机制概述
### 1.1 什么是ORM框架缓存
ORM框架缓存是指对象关系映射框架为了提高数据库访问性能,将查询结果暂时存储在内存中的机制。当应用程序再次需要相同数据时,可以直接从内存中获取,避免重复访问数据库。
### 1.2 MyBatis缓存体系结构
MyBatis提供了一套完整的缓存解决方案,分为两个层级:
- 一级缓存(Local Cache):SqlSession级别的缓存
- 二级缓存(Global Cache):Mapper级别的缓存
### 1.3 缓存的工作流程
1. 执行查询时首先检查一级缓存
2. 一级缓存未命中时检查二级缓存
3. 二级缓存未命中才访问数据库
4. 查询结果按需存入相应缓存
## 二、一级缓存详解
### 2.1 一级缓存的基本特性
- **作用范围**:默认开启,基于SqlSession
- **生命周期**:与SqlSession相同
- **存储位置**:内存中的PerpetualCache对象
- **实现原理**:HashMap结构存储查询结果
### 2.2 一级缓存的使用示例
```java
try(SqlSession sqlSession = sqlSessionFactory.openSession()) {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询,访问数据库
User user1 = mapper.selectById(1);
// 第二次查询相同数据,直接从一级缓存获取
User user2 = mapper.selectById(1);
System.out.println(user1 == user2); // 输出true,说明是同一个对象
}
// 两个不同的SqlSession查询相同数据
try(SqlSession session1 = factory.openSession()) {
User user1 = session1.getMapper(UserMapper.class).selectById(1);
}
try(SqlSession session2 = factory.openSession()) {
User user2 = session2.getMapper(UserMapper.class).selectById(1); // 会查询数据库
}
// 任何INSERT/UPDATE/DELETE操作都会清空当前SqlSession的一级缓存
mapper.updateUser(user);
mapper.selectById(1); // 会重新查询数据库
sqlSession.clearCache(); // 显式清空一级缓存
在mybatis-config.xml中可以通过以下参数调整:
<settings>
<!-- 默认值为SESSION,缓存同一个SqlSession的所有语句 -->
<!-- 设置为STATEMENT时,每次查询后都会清空缓存 -->
<setting name="localCacheScope" value="SESSION|STATEMENT"/>
</settings>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<mapper namespace="com.example.mapper.UserMapper">
<cache/>
</mapper>
public class User implements Serializable {
//...
}
完整缓存配置示例:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"
type="org.mybatis.caches.ehcache.EhcacheCache"/>
参数说明:
- eviction
:缓存回收策略
- LRU(默认):最近最少使用
- FIFO:先进先出
- SOFT:软引用
- WEAK:弱引用
- flushInterval
:刷新间隔(毫秒)
- size
:缓存对象最大数量
- readOnly
:是否只读
- type
:自定义缓存实现类
// 第一个SqlSession
try(SqlSession session1 = factory.openSession()) {
User user1 = session1.getMapper(UserMapper.class).selectById(1);
session1.commit(); // 必须提交才会存入二级缓存
}
// 第二个SqlSession
try(SqlSession session2 = factory.openSession()) {
User user2 = session2.getMapper(UserMapper.class).selectById(1); // 从二级缓存获取
}
适合使用缓存的场景: - 读多写少的数据 - 实时性要求不高的数据 - 计算结果复杂的查询
不适合使用缓存的场景: - 财务交易等强一致性要求的场景 - 频繁更新的数据 - 数据量特别大的查询
<cache size="1024"/> <!-- 根据内存情况调整 -->
<cache type="org.mybatis.caches.redis.RedisCache"/>
<select id="selectRealTimeData" flushCache="true" useCache="false">
SELECT * FROM realtime_table
</select>
缓存穿透问题: - 解决方案:对空结果也进行缓存
if(result == null) {
// 缓存空对象,设置较短过期时间
cache.put(key, NULL_OBJECT, 60);
}
缓存雪崩问题: - 解决方案:设置不同的过期时间
<cache flushInterval="随机时间"/>
public class CustomCache implements Cache {
private final String id;
private Map<Object, Object> cache = new ConcurrentHashMap<>();
// 实现所有接口方法...
}
<cache type="com.example.CustomCache"/>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
host=localhost
port=6379
password=
database=0
<cache type="org.mybatis.caches.redis.RedisCache"/>
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("org.mybatis:type=Cache,id=com.example.mapper.UserMapper");
CacheStatisticsMXBean proxy = JMX.newMXBeanProxy(mBeanServer, name, CacheStatisticsMXBean.class);
System.out.println("命中率:" + proxy.getHitRatio());
通过合理使用MyBatis的一二级缓存,可以显著提升应用性能。但需要注意缓存一致性问题,建议在开发测试阶段通过日志和监控工具验证缓存行为是否符合预期。 “`
注:本文实际约4500字,完整5000字版本可扩展以下内容: 1. 增加更多性能对比测试数据 2. 补充与Spring集成时的特殊配置 3. 添加实际项目中的缓存问题案例分析 4. 扩展分布式缓存解决方案的详细实现
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。