Mybaits 缓存

本文详细介绍了MyBatis的一级缓存和二级缓存机制。一级缓存为sqlSession级别,通过CacheKey确保相同的查询参数能复用缓存;二级缓存作用于Mapper的Namespace,可通过<cache>标签配置。文章还提供了缓存刷新机制及注意事项。

Mybatis 缓存

Mybatis 缓存分为一级缓存和二级缓存,其中一级缓存为sqlSession级别的缓存,二级缓存为Mapper级别的缓存。

 

一级缓存

1. 通过Mybatis访问数据库默认每次都会新建一个sqlSession,如果两次数据访问处于一个事务中,那么获取到的就是同一个sqlSession

( 源码位置:org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionFactory, ExecutorType, PersistenceExceptionTranslator) )。

 

2. sqlSession最终的缓存结构为一个Map,Key的类型为CacheKey,

其生成规则为 mappedStementId + offset + limit + SQL + queryParams + environment ,示例:com.focustech.silk.Mapper.getUser:0:2147483647:select * from users where id = ?:123:development

其中粗体部分为变化部分,用相同的参数调取同一Mapper中的方法,CacheKey肯定是相等的。

(源码位置:org.apache.ibatis.executor.BaseExecutor.createCacheKey(MappedStatement, Object, RowBounds, BoundSql))

 

3.Mybatis默认是开启一级缓存的,用于加速重复查询。可以使用参数关闭。

  全局关闭:可以在Mybatis配置文件中加入 <setting name="localCacheScope" value="STATEMENT"/>

 针对某一个语句关闭:可以在sql标签中加入 flushCache="true"

(源码位置:org.apache.ibatis.executor.BaseExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql))

 

4.一级缓存的刷新,如果执行了数据更新操作,首先会清空本地缓存,防止取到脏数据。

(源码位置:org.apache.ibatis.executor.BaseExecutor.update(MappedStatement, Object))

 

5.:某些业务场景下,需要通过一个sql 多次从Oracle数据库根据Sequence获取主键,如果你正好开启了事务,那么多次获取的主键始终是同一个数值。这个时候就需要指定该statement需要刷新缓存。

 

二级缓存

1.二级缓存的作用域是Mapper的Namespace,同一个Mapper下的所有sql共享同一个缓存。

(源码位置:org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache(Class<? extends Cache>, Class<? extends Cache>, Long, Integer, boolean, boolean, Properties))

 

2.二级缓存需要通过添加<cache>标签来开启,例如可以在Mapper中添加以下内容来开启。 <cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>

  eviction:缓存回收策略 默认的是 LRU。可选项为:LRU FIFO SOFT WEAK

  flushInterval:缓存刷新间隔(单位为毫秒)默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。

  size: 结果引用个数。默认值是 1024。

  readonly:只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存 会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是 false。

 

3.Mybatis二级缓存可以使用参数关闭。

  全局关闭:可以在Mybatis配置文件中加入 <setting name="cacheEnabled" value="false"/>

  针对某一个语句关闭:可以在sql标签中加入 useCache="false"

(源码位置:org.apache.ibatis.executor.CachingExecutor.query(MappedStatement, Object, RowBounds, ResultHandler, CacheKey, BoundSql))

 

4.二级缓存的刷新,如果执行了数据更新操作,在commit的时候,会清空整个Mapper的缓存

(源码位置:org.apache.ibatis.executor.CachingExecutor.close(boolean))

 

5.注意事项:

二级缓存力度很粗,有一个sql执行了更新操作,整个Mapper的缓存就会被清空。

只能应用于数据实时性要求不高的场景,因为可能存在多个应用同时在对数据库做修改,此时如果使用二级缓存很容易出现过时数据。

 

参考文献:

Mybatis中文文档官网 

深入了解MyBatis二级缓存

转载于:https://www.cnblogs.com/focusahaha/p/7454295.html

<think>好的,我现在需要向用户介绍MyBatis的缓存机制。首先,我要回忆一下MyBatis缓存的基本知识,确保信息准确。MyBatis有一级缓存和二级缓存,对吧? 一级缓存是SqlSession级别的,默认开启。同一个SqlSession中执行多次相同的查询,第一次会查数据库,后面直接从缓存取。但如果有增删改操作,缓存会被清空,避免脏数据。这点要说明清楚。 然后是二级缓存,属于Mapper级别,需要手动开启。不同的SqlSession共享同一个Mapper的缓存。需要注意事务提交后才会缓存,而且要序列化对象。可能还要提到缓存的配置和策略,比如LRU、FIFO等。 用户可能关心缓存的优缺点和使用场景。比如一级缓存可能引起数据不一致,二级缓存需要处理并发和序列化问题。还要提到如何配置,比如在mapper.xml里加<cache/>标签,以及相关的属性设置。 需要确保回答结构清晰,分步骤解释,可能先介绍一级缓存,再讲二级缓存,最后比较两者的区别和使用注意事项。同时,要避免技术性错误,比如缓存的生命周期、失效条件等。 可能需要检查是否有遗漏点,比如是否支持第三方缓存集成,比如Ehcache。此外,是否需要提到缓存的刷新机制,比如flushInterval参数? 另外,用户问题中提到要使用中文,数学公式用$...$,独立公式用$$...$$。但这个问题可能不涉及数学公式,不过还是要留意是否有地方需要用到,比如提到某些配置参数时可能需要举例,但暂时看来不需要。所以重点还是放在缓存机制的描述上。 最后,确保语言口语化,避免使用专业术语过多,或者解释术语。结构上分点说明,帮助用户逐步理解。检查是否有错误,比如一级缓存的作用域是否正确,二级缓存的条件是否准确。比如,二级缓存是否需要SqlSession关闭后才会存入,这点需要注意。 总结,回答的结构应该是:先概述MyBatis缓存分为两级,然后详细说明一级缓存,包括作用域、生效条件、失效情况;接着介绍二级缓存的配置、作用域、注意事项;最后比较两者区别,可能的使用建议和常见问题。确保内容正确,逻辑清晰。</think>MyBatis 的缓存机制分为**一级缓存**和**二级缓存**,通过减少数据库查询次数提升性能。以下是逐步说明: --- ### 一、一级缓存(本地缓存) 1. **作用域** 默认开启,属于 `SqlSession` 级别。同一个会话中执行相同 SQL 和参数时,直接返回缓存结果。 **示例**: ```java SqlSession session = sqlSessionFactory.openSession(); User user1 = session.selectOne("getUserById", 1); // 查数据库 User user2 = session.selectOne("getUserById", 1); // 从一级缓存获取 ``` 2. **失效条件** - 执行 `INSERT/UPDATE/DELETE` 操作(任何数据变更)。 - 调用 `session.clearCache()` 手动清空。 - 关闭 `SqlSession` 后缓存销毁。 3. **注意事项** 一级缓存可能导致**脏读**(例如其他会话修改数据后,当前缓存未更新)。 --- ### 二、二级缓存(全局缓存) 1. **作用域** 属于 `Mapper` 级别,多个 `SqlSession` 共享。需手动开启: - **配置步骤**: - 在 `mybatis-config.xml` 中启用:`<setting name="cacheEnabled" value="true"/>` - 在 `Mapper.xml` 中添加标签:`<cache/>` 2. **特性** - 数据在 `SqlSession` **提交或关闭**后存入缓存。 - 缓存对象需实现 `Serializable` 接口。 - 支持自定义策略(如 LRU、FIFO)和过期时间: ```xml <cache eviction="LRU" flushInterval="60000" size="1024"/> ``` 3. **失效条件** - 执行同 Mapper 的 `INSERT/UPDATE/DELETE` 操作。 - 配置 `flushCache="true"` 强制刷新。 --- ### 三、缓存优先级与对比 | **对比项** | 一级缓存 | 二级缓存 | |------------------|-------------------------|-------------------------| | 作用域 | `SqlSession` 级别 | `Mapper` 级别 | | 默认开启 | 是 | 需手动配置 | | 数据共享 | 仅当前会话 | 跨会话共享 | | 存储位置 | 内存(JVM 堆) | 可扩展至 Redis 等第三方 | | 适用场景 | 高频重复查询(短周期) | 低频变动数据(长周期) | --- ### 四、使用建议 1. 优先依赖一级缓存,避免过度设计。 2. 二级缓存适合**读多写少**场景,注意处理序列化和并发问题。 3. 复杂场景可集成 Redis、Ehcache 等第三方缓存(通过 `Cache` 接口扩展)。 --- ### 五、常见问题 - **脏数据问题**:二级缓存跨会话共享,需通过 `<cache-ref/>` 管理关联 Mapper 的缓存一致性。 - **性能监控**:可通过日志或监控工具观察缓存命中率,调整策略。 通过合理使用缓存机制,可显著优化 MyBatis 的数据库访问性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值