MyBatis二级缓存 完成版

本文介绍了MyBatis中的一级缓存与二级缓存机制,详细解释了它们的作用域、生命周期以及工作原理。一级缓存是SqlSession级别的,随SqlSession关闭而销毁;二级缓存则与整个应用的生命周期相同。文章还探讨了缓存的使用场景及其对查询性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一级缓存和二级缓存

 

查询缓存 

查询缓存的运行流程:

代码中的查询语句首先去缓存里尝试着读取一下,查看有没有,如果有的话直接返回,但是如果没有读取到的话,那么他去数据库读取SQL,然后SQL会把得到的查询结果先返回给缓存空间,最后呢在返回给我们的调用方,这就是缓存的工作机制。

接下首先自学

 

Mybatis的缓存,根据它的作用域和生命周期分为两种:

 

作用域区分:mybatis查询缓存的作用域是根据命名空间namespace划分的,相同的命名空间下的mapper放到同一个缓存区,无论是一级还是二级缓存 都是根据namespace存放的。

A命名空间下(比如学生这个namesp下的东西)那它存储和学生相关的东西,都在A命名空间下。

B命名空间下(比如部门这个namesp下的东西)那它存储和部门相关的东西,都在B命名空间下。

这是按命名空间来分的

一级和二级的不同

一级是SqlSession级别的,一旦SqlSession关闭,那么一级缓存中的数据就销毁了。

二级的生命周期与整个应用同步,与SqlSession关闭与否没有半毛线关系

换句话说就是一级缓存是在一个线程内共享数据,然而二级缓存是在n个线程内共享数据

一级缓存

小配置Sql语句

 

 

单测

 

 

方法

 

控制台

 

因为mybatis的一级缓存是不可卸载的。

什么叫不可卸载 就是天然集成,只要你用这个框架,一级缓存就没法消除(注意:数据消除不算卸载)。

重点:mybatis中是根据什么来区分他是一个线程内共享数据也就是一级缓存的依据是什么?

答案:mybatis缓存的底层是个map集合,mapvalue是查询结果,mapkey则是查询依据,根据框架的架构不同,查询依据是不同的。所有mybatis的查询依据是Sqlid(小配置的对应的sql语句的id+SQL语句(单测的数据赋值例如:查id23,所有sql语句是不同的也不能一级缓存)。

注意:系统增删改频繁千万不能用缓存!!!!

必须使用insert标签,不能使用select,否则试验不能成功。

二级缓存:

二级缓存分为:

内置二级缓存:由于mybatis从缓存中读取的依据与SQLid相关,而并非查询出的对象,所以使用二级缓存的目的是:不是在多个查询之间共享查询结果(所有查询中只要查询结果中存在该对象,就直接从缓存中读取,这就是查询结果的共享),而是为了防止同一查询(相同的sqlid和相同的sql语句)的反复执行。

第三方二级缓存:

 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------








### MyBatis 一级缓存的工作原理 MyBatis 的一级缓存是基于 `SqlSession` 实现的,默认情况下,每个 `SqlSession` 都有一个独立的一级缓存区域[^3]。这意味着在同一 `SqlSession` 范围内执行相同的 SQL 查询时,如果查询参数相同,则不会再次访问数据库,而是直接从缓存中返回结果。 #### 缓存存储位置 一级缓存的数据存储在内存中的一个 Map 结构里,键为查询语句及其参数的唯一标识符,值为查询的结果集。这种设计使得重复查询能够快速命中缓存并减少对数据库的压力[^1]。 #### 失效场景 尽管一级缓存能显著提升性能,但它并非始终有效。以下情况会导致一级缓存失效: - 当前 `SqlSession` 执行了任何修改操作(如 INSERT、UPDATE 或 DELETE),因为这些操作可能改变底层数据的状态。 - 显式调用了 `clearCache()` 方法手动清除了当前 `SqlSession` 的缓存。 - 不同的 `SqlSession` 对象之间无法共享缓存内容,即使它们执行的是完全一致的查询逻辑[^3]。 #### 使用场景 为了充分利用 MyBatis 一级缓存带来的优势,建议将其应用于如下场景: - **短生命周期事务**:在一个较短时间内完成的操作流程中频繁读取同一份数据,此时可以通过开启单个 `SqlSession` 来利用其内置的一级缓存功能。 - **只读模式下的批量处理**:对于只需要检索而无需更新的情况,比如报表生成或者数据分析任务,可以考虑通过保持同一个 `SqlSession` 提高效率[^4]。 以下是展示如何正确使用 MyBatis 一级缓存的一个简单例子: ```java // 创建 SqlSession 并保持它在整个过程中可用 try (SqlSession sqlSession = sqlSessionFactory.openSession()) { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 第一次查询触发实际SQL请求到DB User userFirstQuery = userMapper.getUserById(1); System.out.println(userFirstQuery.getName()); // 假设没有其他影响此记录状态的变化发生... // 下面第二次查询应该会命中缓存而不是再发新的SQL给DB User userSecondQuery = userMapper.getUserById(1); System.out.println(userSecondQuery.getName()); } catch(Exception e){ throw new RuntimeException(e.getMessage(),e); } ``` ### 注意事项 需要注意的是,由于一级缓存仅限于单个 `SqlSession` 生命周期之内生效,所以在分布式环境下跨多个服务实例间协作时并不能依赖于此特性来同步最新本的信息[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值