目录
MyBatis 是一个优秀的持久层框架,提供了两级缓存机制:一级缓存和二级缓存。
缓存
什么是缓存?
缓存(Cache)是一种用于提高数据访问速度的技术,通过在存储系统中(内存)保留一部分常用或者最近使用的数据,减少访问底层数据源(如数据库,文件系统等)的频率,从而提供系统性能和响应速度。
缓存的工作原理
缓存的基本原理是利用快速访问存储设备(如内存)来临时存储频繁访问的数据。当需要访问某个数据时,首先检查缓存中是否存在该数据。如果缓存中存在,则直接返回数据;如果不存在,则从底层数据源获取数据,并将该数据存储在缓存中,以备下次访问。
缓存的优点
- 提高性能:缓存可以显著减少数据访问的时间,提升系统的整体性能。
- 减少数据源负载:通过缓存减少对底层数据源的访问频率,减轻数据源的负载。
- 节省带宽:缓存可以减少网络传输的数据量,节省带宽资源。
Mybatis缓存
MyBatis 是一个优秀的持久层框架,提供了两级缓存机制:一级缓存和二级缓存。
一级缓存:将查询的数据存储到sqlSession中
二级缓存:将查询的数据存储到sqlSessionFactory中
注:mybatis缓存只针对DQL语句,也就是只针对select语句
一级缓存(sqlSession级别缓存)
一级缓存的工作原理
- 作用范围:一级缓存的作用范围是 SqlSession,即同一个 SqlSession 中的查询结果会被缓存,不同的 SqlSession 之间互不影响。
- 缓存数据:在同一个 SqlSession 中,如果执行了相同的 SQL 语句(包括参数相同),则会直接从缓存中获取结果。
- 失效条件:
- SqlSession 执行了
insert
、update
、delete
操作,缓存会清空。 - SqlSession 被关闭。
- 手动清空缓存:
SqlSession.clearCache()
。
- SqlSession 执行了
一级缓存的使用
一级缓存是 MyBatis 的默认行为,无需额外配置即可使用。在同一个 SqlSession 中,多次执行相同的查询操作,只有第一次会发送 SQL 语句到数据库,后续的查询操作会直接从缓存中获取结果。
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询,发送 SQL 语句到数据库
User user1 = userMapper.selectUserById(1);
// 第二次查询,从缓存中获取结果
User user2 = userMapper.selectUserById(1);
sqlSession.close();
2024-07-30 08:46:01.590 DEBUG 31608 --- [main] c.x.execute.dao.UserDao.selectById : ==> Preparing: select * from tb_user_info where id = ?
2024-07-30 08:46:01.590 DEBUG 31608 --- [main] c.x.execute.dao.UserDao.selectById : ==> Parameters: 1(Integer)
2024-07-30 08:46:01.591 DEBUG 31608 --- [main] c.x.execute.dao.UserDao.selectById : <== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3713bedc]
User(id=1, userName=null, password=123, gender=男, addr=北京)
User(id=1, userName=null, password=123, gender=男, addr=北京)
从上述代码中可以看到,我们虽然访问了两次同一条DQL语句,但实际上值访问一次数据库,第二次就直接输出了,并没有执行DQL语句。说明该代码指进行了从硬盘读取数据,第二次直接从缓存中拿到我们需要的数据。
二级缓存(sqlSessionFactory级别)
缓存作用域:
二级缓存的作用范围是整个 SQLSessionFactory,也就是说,同一个 SQLSessionFactory 下创建的多个 SQLSession 可以共享二级缓存的数据。
缓存存储:
二级缓存会将查询结果存储在缓存中,当同样的查询再次执行时,会直接从缓存中获取结果,而不是重新查询数据库。
缓存的有效性:
二级缓存是以 namespace 为单位的,也就是说,每个 mapper 的二级缓存是独立的,不同 mapper 之间的缓存数据不会共享。
启用二级缓存
1.在全局配置文件中启用二级缓存
启用二级缓存需要在全局配置文件和 Mapper 文件中进行配置。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
2.在 Mapper 文件中启用二级缓存
在需要使用二级缓存的 Mapper XML 文件中添加 <cache/>
标签:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<cache/>
<select id="selectUserById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
二级缓存的使用
二级缓存启用后,不同的 SqlSession 实例之间可以共享缓存数据。例如:
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
// 第一次查询,发送 SQL 语句到数据库
User user1 = userMapper1.selectUserById(1);
// 关键一步:关闭后,才会把数据放到二级缓存sqlSessionFactory
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
// 第二次查询,从二级缓存中获取结果
User user2 = userMapper2.selectUserById(1);
sqlSession2.close();
二级缓存相关配置
-
eviction(回收策略):可以设置不同的回收策略,如 LRU、FIFO、SOFT 和 WEAK。
-
LRU:最近最少使用,移除最长时间不被使用的对象。
-
FIFO:先进先出,按对象进入缓存的顺序移除。
-
SOFT:软引用,基于垃圾收集器状态和软引用规则移除对象。
-
WEAK:弱引用,更积极地移除对象,基于垃圾收集器状态和弱引用规则。
-
-
flushInterval(刷新间隔):可以设置一个时间间隔,以毫秒为单位,缓存会在该时间间隔后自动刷新。
-
size(引用数目):可以设置缓存中存储的对象或列表的引用数量,需要根据可用内存资源来决定。
-
readOnly(只读):设置为 true 时,所有调用者将获得缓存对象的相同实例,这些对象不能被修改,提供了性能优势。设置为 false 时,缓存对象可以被修改,但会返回对象的拷贝,这会降低性能。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
-
eviction="FIFO":使用先进先出的策略来管理缓存。
-
flushInterval="60000":每 60 秒刷新一次缓存。
-
size="512":缓存可以存储 512 个引用。
-
readOnly="true":缓存对象是只读的,不能被修改。
MyBatis 二级缓存的回收策略
MyBatis 提供了多种缓存实现策略,用户可以选择合适的缓存实现,以满足具体的业务需求。
MyBatis 支持的常见缓存回收策略包括:
- LRU(Least Recently Used):最近最少使用策略。
- FIFO(First In First Out):先进先出策略。
- Soft Cache:基于软引用的缓存策略,当内存不足时自动回收。
- Weak Cache:基于弱引用的缓存策略,当对象没有强引用时自动回收。