Mybatis的一级缓存和二级缓存及其区别

今天来讲一下Mybatis的一级缓存, 二级缓存及其区别

目录

一. 缓存是什么

二. 一级缓存

        一级缓存是什么

        一级缓存何时清空?

        一级缓存的流程图

三. 二级缓存

        二级缓存是什么

        二级缓存何时存入

        二级缓存有过期时间,但没有后台线程进行检测 

        二级缓存的流程图

注意事项


一. 缓存是什么

        缓存其实就是存储在内存中的临时数据,这里的数据量会比较小,一般来说,服务器的内存也是有限的,不可能将所有的数据都放到服务器的内存里面,所以, 只会把关键数据放到缓存中,  这样的话访问起来非常快, 而且方便(doge),当 Mybatis 调用 Dao 层查询数据库时,先查询二级缓存,二级缓存中无对应数据,再去查询一级缓存,一级缓存中也没有,最后去数据库查找。

二. 一级缓存

        一级缓存是什么

         一级缓存作用域是sqlsession级别的,同一个sqlsession中执行相同的sql查询(相同的sql和参数),第一次会去查询数据库并写到缓存中,第二次从一级缓存中取。

        一级缓存何时清空?

        如果中间sqlSession去执行commit操作(执行插入、更新、删除),则会清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。一级缓存时执行commit,close,增删改等操作,就会清空当前的一级缓存;当对SqlSession执行更新操作(update、delete、insert)后并执行commit时,不仅清空其自身的一级缓存(执行更新操作的效果),也清空二级缓存(执行commit()的效果)。

        一级缓存的流程图

三. 二级缓存

        二级缓存是什么

        二级缓存指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。

        二级缓存是 mapper 映射级别的缓存,多个 SqlSession 去操作同一个 Mapper 映射的 sql 语句,多个SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。

        二级缓存何时存入

        在关闭sqlsession后(close),才会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。

        开启了二级缓存后,还需要将要缓存的pojo实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储介质多种多样,不一定只存在内存中,有可能存在硬盘中。

        二级缓存有过期时间,但没有后台线程进行检测 

            
        需要注意的是,并不是key-value的过期时间,而是这个cache的过期时间,是flushInterval,意味着整个清空缓存cache,所以不需要后台线程去定时检测。

每当存取数据的时候,都有检测一下cache的生命时间,默认是1小时,如果这个cache存活了一个小时,那么将整个清空一下。

 

        二级缓存的流程图

 

注意事项

  1. 映射语句文件中的所有 select 语句的结果将会被缓存。
  2. 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  3. 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  4. 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  5. 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  6. 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
     
### MyBatis 一级缓存二级缓存的作用与区别 #### 一、MyBatis 一级缓存的作用 MyBatis一级缓存主要作用在于提升单个 `SqlSession` 范围内的查询效率。当同一个 `SqlSession` 执行多次相同 SQL 查询时,如果数据未被修改,则可以直接从缓存中获取结果,无需再次访问数据库[^1]。 - **特点**: - 基于 `SqlSession` 实现。 - 数据仅限当前 `SqlSession` 使用,无法跨会话共享。 - 自动维护,开发者无需额外配置即可启用。 - **局限性**: - 如果 `SqlSession` 关闭或提交事务后,一级缓存会被清空[^4]。 - 不适用于分布式场景或多线程环境下的数据共享需求。 ```java // 示例:同一 SqlSession 下的一级缓存生效 try (SqlSession session = sqlSessionFactory.openSession()) { User user1 = session.selectOne("getUserById", 1); User user2 = session.selectOne("getUserById", 1); // 此次查询命中一级缓存 } ``` --- #### 二、MyBatis 二级缓存的作用 MyBatis二级缓存旨在进一步优化性能,支持多个 `SqlSession` 共享缓存数据。它通常应用于频繁读取且不常变化的数据表,能够显著降低数据库压力[^3]。 - **特点**: - 基于 Mapper 文件的命名空间 (`namespace`) 配置。 - 支持自定义实现缓存策略(如 Ehcache 或 Redis)。 - 多个 `SqlSession` 可以共享同一块缓存区域。 - **工作流程**: - 第一次查询时,将结果存储至二级缓存。 - 后续同名查询优先从二级缓存加载数据,而非重新执行 SQL[^3]。 ```xml <!-- 开启二级缓存 --> <cache /> <select id="selectUser" resultType="User"> SELECT * FROM users WHERE id = #{id}; </select> ``` --- #### 三、一级缓存二级缓存区别 | 特性 | 一级缓存 | 二级缓存 | |--------------------|---------------------------------------------|---------------------------------------------| | **范围** | 单个 `SqlSession` | 多个 `SqlSession` | | **生命周期** | 随 `SqlSession` 生命周期结束而清除 | 存活时间较长,可持久化 | | **共享能力** | 不支持跨会话共享 | 支持跨会话共享 | | **默认行为** | 默认开启 | 默认关闭 | | **适用场景** | 小规模、短周期操作 | 大规模、高频率读取操作 | 需要注意的是,在 Spring 整合 MyBatis 场景下,由于每次请求都会创建新的 `SqlSession`,因此一级缓存的实际效果有限[^5]。 --- ### 总结 一级缓存二级缓存均是为了减少数据库交互次数而设计的机制。前者专注于单一 `SqlSession` 内部的高效利用;后者则扩展了缓存边界,允许不同会话间共享资源。合理选择两者取决于具体业务需求以及系统的并发特性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值