深入解析Mybatis中缓存机制及优缺点

 更新时间:2025年08月29日 11:40:45   作者:青鱼入云  
MyBatis缓存分为一级(SqlSession级,自动维护)和二级(Mapper级,需配置),通过减少数据库访问提升性能,但存在脏数据和分布式不兼容风险,适合高频查询低频修改场景,需合理配置以平衡效率与一致性,本文给介绍Mybatis中缓存机制及优缺点,感兴趣的朋友跟随小编一起看看吧

MyBatis 提供了完善的缓存机制,用于减少了数据库访问次数,提升查询性能。其缓存体系分为一级缓存(本地缓存)和二级缓存(全局缓存),两者配合使用形成了 MyBatis 的缓存体系。

一、MyBatis 缓存机制详解

1. 一级缓存(Local Cache)

  • 作用范围:SqlSession 级别(即同一个数据库会话内有效)。
  • 实现原理:默认开启,无需配置。MyBatis 在 SqlSession 内部维护一个 HashMap 作为缓存容器,键为 CacheKey(由 SQL 语句、参数、RowBounds、环境等信息生成),值为查询结果。
  • 生命周期:与 SqlSession 一致,当 SqlSession 关闭(close())或提交(commit())、回滚(rollback())时,一级缓存会被清空。
  • 触发场景
  • 同一 SqlSession 中,执行相同的查询(SQL 语句、参数、分页等完全一致),会直接从缓存获取结果,不执行 SQL。
  • 若 SqlSession 中执行了增删改操作(insert/update/delete),MyBatis 会自动清空一级缓存,避免脏数据。

2. 二级缓存(Global Cache)

  • 作用范围:Mapper 接口级别(跨 SqlSession 共享,多个 SqlSession 可共享同一 Mapper 的缓存)。
  • 实现原理:默认关闭,需手动开启。开启后,MyBatis 会为每个 Mapper 接口创建一个缓存对象(可自定义缓存实现,如 Redis、EhCache 等),查询结果会先存入一级缓存,当 SqlSession 关闭时,一级缓存的数据会被刷入二级缓存。
  • 开启方式
  1. 在 MyBatis 配置文件中开启全局二级缓存(默认 true,可省略):
xml
 <settings>
     <setting name="cacheEnabled" value="true"/>
 </settings>
  1. 在 Mapper 接口或 XML 中声明使用二级缓存:
 - XML 方式:在 Mapper.xml 中添加 `<cache/>` 标签。
 - 注解方式:在 Mapper 接口上添加 `@CacheNamespace` 注解。
  • 缓存策略:可通过 <cache> 标签的属性配置,如 eviction(回收策略,如 LRU、FIFO)、flushInterval(自动刷新时间)、size(最大缓存条目)、readOnly(是否只读)等。
  • 触发清空:当 Mapper 中执行增删改操作时,MyBatis 会清空该 Mapper 对应的二级缓存。

3. 缓存执行顺序

查询数据时,MyBatis 会按以下顺序查找缓存:
二级缓存 → 一级缓存 → 数据库

  • 若二级缓存命中,直接返回结果。
  • 若二级缓存未命中,查询一级缓存,命中则返回。
  • 若一级缓存也未命中,执行 SQL 查询数据库,结果依次存入一级缓存和二级缓存(当 SqlSession 关闭时)。

二、MyBatis 缓存的优点

  1. 减少数据库访问:缓存命中时无需执行 SQL,降低数据库压力,尤其适合高频查询、低频修改的数据(如商品分类、字典表)。
  2. 提升查询性能:缓存查询为内存操作,响应速度远快于数据库 IO,可显著减少接口响应时间。
  3. 一级缓存自动维护:无需手动配置,默认生效,适合单会话内的重复查询(如一次请求中多次查询同一用户信息)。
  4. 二级缓存灵活性高:支持自定义缓存实现(如集成 Redis 实现分布式缓存),可根据业务需求配置回收策略、过期时间等。
  5. 与事务兼容:增删改操作会自动清空相关缓存,减少脏数据风险(需正确使用)。

三、MyBatis 缓存的缺点

  1. 一级缓存局限性
  • 仅在 SqlSession 内有效,多会话共享数据需依赖二级缓存。
  • 若 SqlSession 未关闭,长时间持有缓存可能导致数据过期(如其他会话修改了数据,当前会话仍使用旧缓存)。
  1. 二级缓存潜在问题
  • 脏数据风险:多表关联查询时,若关联表的数据在其他 Mapper 中修改,当前 Mapper 的二级缓存可能未同步更新,导致查询到脏数据。
    例如:OrderMapper 缓存了包含用户信息的订单数据,若 UserMapper 修改了用户信息,OrderMapper 的缓存仍为旧数据。
  • 分布式环境不兼容:默认二级缓存为本地内存缓存,分布式系统中多节点缓存无法同步,可能导致数据不一致(需集成 Redis 等分布式缓存解决)。
  • 缓存键设计复杂CacheKey 依赖 SQL、参数、分页等信息,若查询条件细微差异(如参数顺序不同),会导致缓存不命中,浪费缓存空间。
  1. 缓存维护成本
  • 需手动配置二级缓存,且需根据业务调整回收策略、过期时间等参数,增加开发成本。
  • 对于高频修改的数据(如库存、订单状态),缓存命中率低,反而可能因缓存更新带来额外开销。
  1. 调试难度增加:缓存的存在可能掩盖 SQL 性能问题(如慢查询因缓存命中未暴露),且排查缓存相关的脏数据问题较为复杂。

四、适用场景与最佳实践

  • 适合使用缓存
  • 高频查询、低频修改的数据(如商品类目、地区信息、字典表)。
  • 单表查询或关联关系简单的查询(避免多表关联导致的缓存不一致)。
  • 分布式环境下,建议使用 Redis 等分布式缓存替代默认二级缓存。
  • 不适合使用缓存
  • 高频修改的数据(如库存、实时销量)。
  • 多表关联复杂的查询(难以保证缓存一致性)。
  • 数据实时性要求极高的场景(如金融交易数据)。
  • 最佳实践
  • 优先利用一级缓存,避免在 SqlSession 中执行无关操作,减少缓存无效清空。
  • 二级缓存按需开启,对核心 Mapper 单独配置,避免全局开启导致的缓存膨胀。
  • 多表关联查询时,可通过 @CacheNamespaceRef 关联相关 Mapper,确保缓存同步清空。
  • 分布式系统中,集成 Redis 作为二级缓存,保证缓存一致性。

总结

MyBatis 缓存机制通过一级缓存和二级缓存的配合,有效提升了查询性能,但也存在缓存一致性、分布式兼容等问题。实际使用中需根据业务场景合理配置,权衡性能与数据准确性,避免滥用缓存导致的隐性问题。

到此这篇关于深入解析Mybatis中缓存机制及优缺点的文章就介绍到这了,更多相关Mybatis缓存机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • htmlcleaner使用方法及xpath语法初探

    htmlcleaner使用方法及xpath语法初探

    HtmlCleaner是一个开源的Java语言的Html文档解析器。HtmlCleaner能够重新整理HTML文档的每个元素并生成结构良好(Well-Formed)的 HTML 文档
    2015-08-08
  • 一文详解Java抽象类到底有多抽象

    一文详解Java抽象类到底有多抽象

    这篇文章主要介绍了一文详解Java抽象类到底有多抽象,抽象方法所在的类必须是抽象类,子类若继承了一个抽象类,就必须覆写父类的所有抽象方法,这里的子类是普通类,是强制要求覆写所有抽象方法,但是如果子类也是一个抽象类,那么就可以不覆写
    2022-06-06
  • MongoDB在Spring Boot中的使用方式举例介绍

    MongoDB在Spring Boot中的使用方式举例介绍

    MongoDB是基于Json数据结构的非关系型数据库,每一个Json文档有一个唯一的主键,下面通过实例代码讲解MongoDB在Spring Boot中的使用方式,感兴趣的朋友一起看看吧
    2025-05-05
  • 一起因MySQL时间戳精度引发的血案分析

    一起因MySQL时间戳精度引发的血案分析

    这篇文章主要给大家介绍了一起因MySQL时间戳精度引发的血案的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用MySQL具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • 使用Lombok导致打印的tostring中缺少父类的属性问题

    使用Lombok导致打印的tostring中缺少父类的属性问题

    使用Lombok时,若发现@Data注解的@ToString不包含父类属性,可通过添加@ToString(callSuper=true)解决,此方法确保在生成toString()时包括父类的属性,有效解决只打印子类属性的问题,这种做法对于需要完整信息展示的场景尤为重要
    2024-11-11
  • spring boot设置过滤器、监听器及拦截器的方法

    spring boot设置过滤器、监听器及拦截器的方法

    这篇文章主要给大家介绍了关于spring boot设置过滤器、监听器及拦截器的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-04-04
  • SpringBoot中的yaml语法及静态资源访问问题

    SpringBoot中的yaml语法及静态资源访问问题

    这篇文章主要介绍了SpringBoot中的yaml语法及静态资源访问问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • SpringMVC文件上传及查看的示例代码

    SpringMVC文件上传及查看的示例代码

    本篇文章主要介绍了SpringMVC文件上传及查看的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • 将JSON字符串数组转对象集合方法步骤

    将JSON字符串数组转对象集合方法步骤

    这篇文章主要给大家介绍了关于将JSON字符串数组转对象集合的方法步骤,文中通过代码示例介绍的非常详细,对大家的学习或者工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • SpringBoot四大神器之Auto onfiguration的使用

    SpringBoot四大神器之Auto onfiguration的使用

    本文主要介绍了SpringBoot四大神器之Auto Configuration,springboot auto configuration的本质就是自动配置spring的各种bean。感兴趣的可以了解一下
    2021-10-10

最新评论