Mybatis缓存
- 一级缓存 (Local Cache)
- 特点:
- 默认启用:MyBatis 一级缓存是自动开启的,无需额外配置。
- 会话级别:一级缓存的作用域局限在同一个 SqlSession 中,即同一个会话内的查询结果会被缓存起来。
- 线程不安全:每个 SqlSession 对象是线程不安全的,因此一级缓存也是线程私有的,不同线程间的 SqlSession 无法共享一级缓存数据。
- 简单快速:一级缓存基于 HashMap 实现,数据读取速度快,适用于简单的缓存场景。
- 生命周期:
- 一级缓存的生命周期与 SqlSession 绑定,当 SqlSession 关闭、过期或显式清除缓存时,一级缓存随之清空。
- 缓存策略:
- 查询时:在同一个 SqlSession 内,当执行相同的查询请求时,MyBatis 会首先在一级缓存中查找结果。如果找到匹配的缓存数据,则直接返回,避免了对数据库的重复查询。
- 更新时:当在同一个 SqlSession 中执行插入、更新、删除等修改数据库的操作时,MyBatis 会自动清空当前 SqlSession 的一级缓存,以确保缓存数据与数据库状态的一致性。
- 适用场景:
- 适用于单个用户或单个操作序列(如一个HTTP请求)内的重复查询,能够有效减少短时间内对同一数据的重复查询。
- 二级缓存 (Global Cache)
- 特点:
- 可配置启用:二级缓存默认关闭,需要在 mybatis-config.xml 文件或 Mapper XML 文件中进行显式配置才能启用。
- Mapper(命名空间)级别:二级缓存的作用域扩大到了同一个命名空间(Mapper)的所有 SqlSession,即多个会话间可以共享同一命名空间的缓存数据。
- 线程安全:二级缓存通常实现为线程安全的数据结构,允许在多线程环境中共享数据。
- 可扩展:二级缓存支持多种第三方缓存插件,如 Ehcache、Redis、Memcached 等,可以根据需求选择合适的缓存实现。
- 生命周期:
- 二级缓存的生命周期与 Mapper 命名空间绑定,当某个命名空间的缓存配置发生变化、或者显式清空缓存时,该命名空间的二级缓存数据才会被清空。
- 缓存策略:
- 查询时:在不同 SqlSession 之间,如果执行相同的查询请求且对应 Mapper 已启用二级缓存,MyBatis 会首先在二级缓存中查找结果。如果找到匹配的缓存数据,则直接返回,否则才查询数据库,并将查询结果存入二级缓存供后续查询使用。
- 更新时:当执行插入、更新、删除等操作时,二级缓存的行为取决于配置。一般情况下,二级缓存会在下一次查询时自动刷新,确保数据新鲜度。但也可以配置为立即刷新或基于某种事件(如JMS消息)触发刷新。
- 适用场景:
- 适用于多用户或长时间跨度内的相同查询,尤其适合那些查询数据变化频率较低且被大量用户共享的场景。
- 总结
- 一级缓存:轻量级、快速响应,适用于单个会话内减少重复查询,但作用范围有限,且与会话生命周期紧密关联。
- 二级缓存:更全局、持久的缓存,适用于跨会话共享查询结果,降低了不同用户或服务间对同一数据的重复查询,但配置较为复杂,且需要考虑数据一致性、缓存同步等问题。
- 在实际使用中,一级缓存和二级缓存可以配合使用,形成多级缓存体系,以更精细的粒度优化查询性能。不过,启用缓存的同时也需要考虑数据一致性、缓存更新策略以及可能引入的并发问题,确保缓存机制在提升性能的同时不会对业务逻辑产生负面影响。