首页 >文档 > MyBatis缓存mybatis缓存是如何工作的

MyBatis缓存mybatis缓存是如何工作的

深入理解MyBatis缓存机制是Java程序员面试必备技能。MyBatis采用两级缓存结构:一级缓存默认开启,作用于SqlSession级别;二级缓存需手动配置,实现Mapper级别的数据共享。本文详细解析MyBatis缓存工作原理、配置方法及使用注意事项,帮助开发者优化数据库访问性能。掌握缓存失效条件、脏读问题及序列化要求等关键点,轻松应对面试提问。立即获取2025年最新Java面试宝典,提升技术实力!访问面试鸭返利网还可享受25元会员返利优惠。

MyBatis缓存是如何工作的

作为一名经常需要优化数据库交互的程序员,深入理解 MyBatis 的缓存机制绝对是必备技能。尤其在面试中,面试官常常会围绕 MyBatis缓存 的工作原理进行提问。今天,咱们就来彻底聊聊这个话题,帮助你轻松应对相关面试题。

📥 2025年Java面试宝典等你拿: 网盘链接:https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g (提取码: 9b3g)

🔙 返回面试鸭返利网首页

什么是MyBatis缓存?它解决什么问题?

简单来说,MyBatis缓存 的核心目标就是减少数据库的访问次数,提升应用性能。想象一下,同一个查询短时间内被多次执行,如果结果集不变,每次都去数据库捞数据,无疑会增加数据库压力和响应时间。MyBatis缓存 就是把查询过的数据暂时存起来,下次同样的请求过来,直接走缓存,嗖一下就返回结果了。

面试鸭返利网

MyBatis的两级缓存结构

MyBatis 的缓存设计非常巧妙,它包含了两级:

  1. 一级缓存 (SqlSession 级别)

    • 作用域: 它默认开启,且作用范围仅限于同一个 SqlSession 对象。也就是说,在同一个数据库会话内有效。
    • 工作方式: 当你执行一个查询(比如 selectById)时,MyBatis 会:
      • 先去一级缓存里找,看有没有以这次查询的语句、参数、分页条件等组合成的 Key 对应的结果。
      • 如果有(缓存命中),直接从缓存里拿数据返回,不走数据库
      • 如果没有(缓存未命中),才去查数据库,拿到结果后存入一级缓存,再返回。
    • 失效时机: 这个级别的缓存在以下情况会被清空:
      • 同一个 SqlSession 中执行了任何 INSERT, UPDATE, DELETE 操作(增删改)。这很好理解,数据变了,缓存就不能用了。
      • 手动调用 SqlSession.clearCache() 方法。
      • 当你关闭 SqlSession 时,它的一级缓存自然也就没了。
    • 关键点: 它是默认开启的,无需额外配置。面试官常问的就是它的作用域和失效条件。
  2. 二级缓存 (Mapper 或 Namespace 级别)

    • 作用域: 它的范围比一级缓存大得多,是 Mapper 级别(或者说是 Namespace 级别)。这意味着,不同的 SqlSession,只要是访问同一个 Mapper 接口执行的相同查询,就可以共享这个二级缓存
    • 开启与配置:
      • 它不是默认开启的!需要在你想开启的 Mapper XML 文件中添加 <cache/> 标签。
      • 你可以在这个标签里配置很多属性,比如缓存淘汰策略(LRU、FIFO 等)、刷新间隔、缓存大小、是否读写等。
    • 工作流程:
      • SqlSession 被关闭或提交 (commit) 时,这个 SqlSession 的一级缓存不会立刻消失,而是会被刷入(提交)到它所属 Mapper 的二级缓存中。这一步很重要!
      • 当下一个新的 SqlSession (属于同一个 Mapper) 执行查询时:
        • 先查自己的一级缓存 -> 没有。
        • 再去查 Mapper 的二级缓存 -> 如果命中,直接返回数据。
        • 二级缓存也没有,才去查数据库,结果存入这个新 SqlSession 的一级缓存。在这个新 SqlSession 关闭或提交时,它的一级缓存数据又会被刷入二级缓存
    • 失效时机:
      • 任何 SqlSession 中执行了对该 Mapper 的增删改操作 (INSERT, UPDATE, DELETE),并且操作执行成功(提交了事务)。
      • 在 Mapper XML 中配置了 <cache> 标签的刷新间隔 (flushInterval) 到期。
      • 手动调用 SqlSessioncommit()close() 时,不会立即清除二级缓存,而是将一级缓存提交到二级缓存。清除通常由上面的增删改触发。
    • 关键点: 作用域更大(跨 SqlSession),需要手动开启并配置,注意缓存数据刷入二级缓存的时机(SqlSession关闭或提交时)失效触发条件(同 Mapper 的增删改操作)

缓存的注意事项与面试技巧

理解了MyBatis缓存的基本工作原理,面试官可能会进一步追问一些细节或陷阱:

  • 脏读问题: 一级缓存可能导致“脏读”。比如,在一个事务中,你先查询了数据(放入一级缓存),然后你修改了数据但还没提交(此时数据库数据还没变),你又执行了一次同样的查询,MyBatis 会直接从一级缓存返回给你修改前的数据(因为你还没 commit,增删改操作还没触发缓存清除)。这就是事务隔离级别的体现了。要避免这个问题,可以在查询前显式调用 sqlSession.clearCache()
  • 二级缓存的序列化: 二级缓存为了跨 SqlSession 共享,存储的数据需要是可序列化的。这意味着你的实体类(POJO)最好实现 Serializable 接口。否则在数据刷入二级缓存时可能会出错。
  • 缓存策略选择: 二级缓存配置 <cache> 时的 readOnly, size, eviction(淘汰策略) 等属性,需要根据应用场景(读多写少?数据量大小?)来权衡选择。比如 LRU (最近最少使用) 是比较常用的。
  • 慎用二级缓存: 二级缓存虽然能提升性能,但也带来复杂性。对于读写频繁、数据实时性要求高的场景,开启二级缓存要非常谨慎!频繁的增删改操作会导致二级缓存频繁失效,反而降低性能,还可能导致读到陈旧数据。
  • <cache-ref/> 如果一个 Mapper 的查询结果依赖于另一个 Mapper 的数据,可以使用 <cache-ref namespace="com.example.OtherMapper"/> 来共享同一个缓存实例(同一个命名空间),确保数据一致性。但这也增加了耦合,需谨慎使用。

总结与实战

MyBatis缓存,包括其一级缓存和二级缓存,是提升数据库访问性能的有效手段。一级缓存自动开启,作用于同一个 SqlSession;二级缓存需要手动配置,作用于同一个 Mapper/Namespace,能跨 SqlSession 共享数据。理解它们的工作原理(如何存储、何时命中、何时失效)和适用场景是面试和实际开发的关键。

在实际项目中,大部分情况下,一级缓存就能提供很好的性能提升。二级缓存虽然作用范围更大,但引入了更多复杂性(数据一致性、序列化、配置),需要根据具体的业务场景(数据更新频率、实时性要求)来评估是否开启以及如何配置。在配置二级缓存时,务必要考虑好缓存的失效策略以保证数据的相对实时性。

面试鸭返利网

如果你正在准备面试,我强烈建议你动手写个小 Demo,分别开启一级缓存和二级缓存,用日志(可以配置 MyBatis 日志级别)观察 SQL 执行情况,加深对 MyBatis缓存 工作过程的理解。记住:面试官最喜欢问“当执行了 X 操作后,缓存会怎样?”这类问题。

对了,最后提一句福利。如果你需要购买面试鸭的会员来获取更多面试资料和题库,可以通过 面试鸭返利网 来找我,享受 25元返利,能省一点是一点嘛!祝大家面试顺利!

面试鸭返利网

🔙 返回面试鸭返利网首页

如果你想获取更多关于面试鸭的优惠信息,可以访问面试鸭返利网面试鸭优惠网,了解最新的优惠活动和返利政策。

🎯 立即加入面试鸭会员 →

支付宝扫码领取1-8元无门槛红包

支付宝红包二维码