MyBatis 的缓存分为一级缓存和二级缓存,两者的主要目的是减少数据库的查询次数,提高应用程序的性能。
MyBatis 默认的一级缓存是会话级别的,也就是说,只在一个 SqlSession
范围内有效。一旦会话被关闭,缓存也就消失了。
工作机制:
PerpetualCache
的哈希表,默认情况下,它只是一个简单的 HashMap
实例。SqlSession
中执行查询,MyBatis 会将查询结果缓存起来。SqlSession
中)和之前的请求完全相同,包括查询语句、参数和分页信息等,MyBatis 会直接从缓存中获取结果。代码示例:
try (SqlSession session = sqlSessionFactory.openSession()) {
BlogMapper mapper = session.getMapper(BlogMapper.class);
// 第一次查询
Blog blog = mapper.selectBlog(101);
// 这里的第二次查询会直接从缓存中获取数据
Blog sameBlog = mapper.selectBlog(101);
}
一级缓存失效场景:
SqlSession
不同。SqlSession
相同,查询条件不同。SqlSession
相同,在两次相同查询之间执行了增删改操作。SqlSession
相同,但是手动清除了缓存。二级缓存是跨 SqlSession
的,它的生命周期不仅限于会话的持续时间,可以跨会话和映射器共享。
工作机制:
<cache/>
标签。SqlSession
间共享,只要它们向同一个 Mapper
发出相同的查询请求。配置示例:
<!-- 在 mybatis-config.xml 中启用二级缓存 -->
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 在对应的 Mapper.xml 文件中配置二级缓存 -->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
代码示例:
假设我们有一个 BlogMapper.xml
,我们在其中启用二级缓存:
<mapper namespace="org.mybatis.example.BlogMapper">
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
<!-- 其他的 SQL 映射语句 -->
</mapper>
接着,我们的 Java 代码可能如下所示:
// 第一个 SqlSession
try (SqlSession session1 = sqlSessionFactory.openSession()) {
BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
Blog blog1 = mapper1.selectBlog(101);
session1.commit(); // 触发二级缓存
}
// 第二个 SqlSession
try (SqlSession session2 = sqlSessionFactory.openSession()) {
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
// 这次查询将会走二级缓存
Blog blog2 = mapper2.selectBlog(101);
}
二级缓存失效场景:
flushCache=true
(默认行为是 true)。SqlSession
调用了 clearCache()
方法。可以通过自定义实现 org.apache.ibatis.cache.Cache
接口来创建自己的缓存类型,这可以让你实现诸如 Redis、Ehcache 等分布式缓存的集成。
示例代码片段:
public class MyCustomCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 需要实现的方法,例如 getId, getSize, putObject, getObject, removeObject, clear 等
@Override
public String getId() {
// 缓存的唯一标识符
}
// 其他方法实现...
}
<!-- 在 Mapper.xml 文件中使用自定义缓存 -->
<cache type="org.mybatis.caches.myown.MyCustomCache"/>
在深入应用 MyBatis 缓存时,考虑缓存配置对应用程序行为的影响是关键。特别是在高并发环境中,缓存的使用可能会导致数据不一致。此外,过多地依赖缓存也可能会导致缓存穿透、缓存雪崩等问题,因此需要谨慎设计缓存的大小、过期策略和同步机制。