Mybatis缓存详解

目录

缓存

什么是缓存?

缓存的工作原理

缓存的优点

Mybatis缓存

MyBatis 是一个优秀的持久层框架,提供了两级缓存机制:一级缓存和二级缓存。

一级缓存(sqlSession级别缓存)

一级缓存的工作原理

一级缓存的使用

二级缓存(sqlSessionFactory级别)

缓存作用域:

缓存存储:

缓存的有效性:

启用二级缓存

1.在全局配置文件中启用二级缓存

2.在 Mapper 文件中启用二级缓存

二级缓存的使用

二级缓存相关配置

MyBatis 二级缓存的回收策略


缓存

什么是缓存?

缓存(Cache)是一种用于提高数据访问速度的技术,通过在存储系统中(内存)保留一部分常用或者最近使用的数据,减少访问底层数据源(如数据库,文件系统等)的频率,从而提供系统性能和响应速度。

缓存的工作原理

缓存的基本原理是利用快速访问存储设备(如内存)来临时存储频繁访问的数据。当需要访问某个数据时,首先检查缓存中是否存在该数据。如果缓存中存在,则直接返回数据;如果不存在,则从底层数据源获取数据,并将该数据存储在缓存中,以备下次访问。

缓存的优点

  1. 提高性能:缓存可以显著减少数据访问的时间,提升系统的整体性能。
  2. 减少数据源负载:通过缓存减少对底层数据源的访问频率,减轻数据源的负载。
  3. 节省带宽:缓存可以减少网络传输的数据量,节省带宽资源。

Mybatis缓存

MyBatis 是一个优秀的持久层框架,提供了两级缓存机制:一级缓存和二级缓存。

一级缓存:将查询的数据存储到sqlSession中

二级缓存:将查询的数据存储到sqlSessionFactory中

:mybatis缓存只针对DQL语句,也就是只针对select语句

一级缓存(sqlSession级别缓存)

一级缓存的工作原理

  1. 作用范围:一级缓存的作用范围是 SqlSession,即同一个 SqlSession 中的查询结果会被缓存,不同的 SqlSession 之间互不影响。
  2. 缓存数据:在同一个 SqlSession 中,如果执行了相同的 SQL 语句(包括参数相同),则会直接从缓存中获取结果。
  3. 失效条件
    • SqlSession 执行了 insertupdatedelete 操作,缓存会清空。
    • SqlSession 被关闭。
    • 手动清空缓存:SqlSession.clearCache()

一级缓存的使用

一级缓存是 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"/>
  1. eviction="FIFO":使用先进先出的策略来管理缓存。

  2. flushInterval="60000":每 60 秒刷新一次缓存。

  3. size="512":缓存可以存储 512 个引用。

  4. readOnly="true":缓存对象是只读的,不能被修改。

MyBatis 二级缓存的回收策略

MyBatis 提供了多种缓存实现策略,用户可以选择合适的缓存实现,以满足具体的业务需求。

MyBatis 支持的常见缓存回收策略包括:

  1. LRU(Least Recently Used):最近最少使用策略。
  2. FIFO(First In First Out):先进先出策略。
  3. Soft Cache:基于软引用的缓存策略,当内存不足时自动回收。
  4. Weak Cache:基于弱引用的缓存策略,当对象没有强引用时自动回收。

  • 40
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值