当前位置: 首页 > article >正文

MyBatis 缓存机制

MyBatis 缓存机制详解

MyBatis 提供了一种内置的缓存机制,用来提高数据查询的效率。通过缓存,MyBatis 可以减少对数据库的访问,提升系统性能。MyBatis 缓存分为 一级缓存(Local Cache)二级缓存(Global Cache),并且可以与第三方缓存框架集成。


1. MyBatis 缓存简介

  • 一级缓存:默认开启,作用范围是会话级别,即同一个 SQLSession 中的查询结果会被缓存。每个 SQLSession 都有自己独立的一级缓存,当 SQLSession 关闭时,一级缓存将被清空。
  • 二级缓存:需要手动开启,作用范围是全局级别(Mapper 级别),不同 SQLSession 之间可以共享二级缓存。二级缓存可以减少重复的数据库访问。

MyBatis 缓存机制的基本工作原理是:

  1. 当执行查询操作时,首先检查缓存中是否存在该查询的结果。
  2. 如果存在缓存,则直接返回缓存数据。
  3. 如果缓存中不存在该查询结果,则访问数据库,并将查询结果存入缓存。

2. 一级缓存

一级缓存是 MyBatis 的默认缓存机制,它不需要额外配置,默认情况下是开启的。每个 SQLSession 都会维护一个本地缓存,用来缓存该 SQLSession 中执行的查询结果。

2.1 一级缓存工作原理
  • 一级缓存的作用范围是同一个 SQLSession。在同一个 SQLSession 中,执行相同的查询,MyBatis 会从缓存中获取数据,而不会再查询数据库。
  • 当执行 insertupdatedelete 操作时,MyBatis 会清空该 SQLSession 的一级缓存,确保数据的一致性。
2.2 一级缓存示例
public class UserService {

    @Autowired
    private SqlSession sqlSession;

    public void testCache() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 第一次查询,结果会从数据库中获取
        User user1 = mapper.getUserById(1);

        // 第二次查询相同的记录,结果会从一级缓存中获取,不会再访问数据库
        User user2 = mapper.getUserById(1);
    }
}

在上述代码中,getUserById 方法被调用两次,第二次查询时 MyBatis 会从一级缓存中获取结果,而不会再访问数据库。

2.3 一级缓存失效条件

一级缓存会在以下情况下失效:

  1. SQLSession 关闭:当 SQLSession 关闭时,一级缓存也会被清空。
  2. 执行更新操作insertupdatedelete 等更新操作会清空该会话的一级缓存,确保数据一致性。
  3. 手动清空缓存:可以通过 sqlSession.clearCache() 手动清空一级缓存。
sqlSession.clearCache();  // 手动清空一级缓存

3. 二级缓存

二级缓存是全局级别的缓存,可以在不同 SQLSession 之间共享。二级缓存的作用范围是Mapper 级别,即同一个 Mapper 中的查询可以被多个 SQLSession 共享。

3.1 二级缓存配置

二级缓存是非默认开启的,需要手动开启。在 MyBatis 中启用二级缓存非常简单,只需要在 Mapper 配置文件或注解中指定开启缓存。

  1. 在 Mapper XML 中启用二级缓存

在 Mapper XML 文件中,通过添加 <cache> 标签来启用二级缓存:

<mapper namespace="com.example.mapper.UserMapper">

    <!-- 启用二级缓存 -->
    <cache/>

    <select id="getUserById" resultType="User">
        SELECT * FROM user WHERE id = #{id}
    </select>
</mapper>
  1. 通过注解方式启用二级缓存

如果使用注解方式配置 Mapper,可以在接口类上添加 @CacheNamespace 注解来启用二级缓存。

import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.Mapper;

@Mapper
@CacheNamespace
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(int id);
}
3.2 二级缓存的工作原理
  • 缓存作用范围:二级缓存是 Mapper 级别的缓存,不同 SQLSession 间的查询结果可以共享。

  • 缓存存储机制:MyBatis 的二级缓存以对象的序列化方式存储。

  • 缓存失效:与一级缓存类似,当执行 insertupdatedelete 操作时,MyBatis 会清空对应的二级缓存。

  • 刷新机制:可以通过 flushInterval 配置自动刷新缓存,单位是毫秒:

    <cache flushInterval="60000"/>  <!-- 60秒刷新一次缓存 -->
    
3.3 二级缓存示例
public class UserService {

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    public void testCache() {
        // 第一个 SQLSession
        SqlSession session1 = sqlSessionFactory.openSession();
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        User user1 = mapper1.getUserById(1);
        session1.close();  // 一级缓存失效,但查询结果会存入二级缓存

        // 第二个 SQLSession
        SqlSession session2 = sqlSessionFactory.openSession();
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user2 = mapper2.getUserById(1);  // 从二级缓存中获取
        session2.close();
    }
}

在上述代码中,session1 执行查询后,结果会存入二级缓存。session2 执行相同的查询时,会从二级缓存中获取数据,而不会再访问数据库。

3.4 配置二级缓存的其他参数

除了 flushInterval<cache> 标签还可以配置其他参数,例如:

  • size:缓存的最大存储对象数目(默认为 1024 个对象)。

    <cache size="500"/>  <!-- 缓存最多存储500个对象 -->
    
  • readOnly:是否开启只读模式,默认值为 false。开启只读模式后,缓存中的数据无法修改,提升并发性能。

    <cache readOnly="true"/>
    
  • eviction:缓存的逐出策略,可以设置为 LRU(Least Recently Used, 最近最少使用),FIFO(先进先出),SOFT(软引用),WEAK(弱引用)。默认策略是 LRU

    <cache eviction="FIFO"/>  <!-- 先进先出策略 -->
    

4. 与第三方缓存整合

MyBatis 支持与其他第三方缓存框架(如 Ehcache、Redis)集成。通过这种方式,可以进一步增强缓存的功能和性能。

4.1 Ehcache 集成

要集成 Ehcache,首先需要引入 Ehcache 依赖:

<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.1.0</version>
</dependency>

然后,在 logback.xml 中指定缓存类型为 Ehcache:

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

最后,配置 Ehcache 的 ehcache.xml

<ehcache>
    <cache name="com.example.mapper.UserMapper"
           maxEntriesLocalHeap="1000"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="3600"
           overflowToDisk="false"/>
</ehcache>

通过这样的配置,MyBatis 可以利用 Ehcache 提供的强大缓存能力来提升缓存性能和扩展性。


5. 缓存机制的注意事项

  1. 缓存一致性问题:当数据库中的数据被修改时,一级缓存和二级缓存需要确保同步更新。如果缓存不能及时清除或刷新,可能会导致缓存和数据库数据不一致的问题。MyBatis 默认会在执行 insertupdatedelete 操作时清空缓存,但在复杂场景下,可能需要手动控制缓存的刷新。
  2. 缓存的适用场景:MyBatis 的缓存适用于查询频率高、变化较少的场景。例如,用户信息、商品分类等查询频繁但数据更新较少的数据适合使用缓存。而对于频繁更新的数据,不建议使用缓存。
  3. 缓存的管理:可以通过 sqlSession.clearCache() 手动清除一级缓存,通过 @CacheNamespace<cache> 标签控制二级

缓存的配置与失效策略。


6. 总结

MyBatis 提供了灵活的一级和二级缓存机制,通过这些缓存机制,可以显著提升查询性能,减少数据库的压力。一级缓存是默认开启的会话级缓存,适用于单次会话中的重复查询。而二级缓存是全局共享的缓存,适合用于查询频率高且数据变化较少的场景。

此外,MyBatis 还支持与 Ehcache、Redis 等第三方缓存框架集成,从而提供更加强大的缓存管理功能。开发者在使用缓存时,应根据实际业务需求灵活配置缓存策略,避免缓存一致性问题。


http://www.kler.cn/news/319628.html

相关文章:

  • 【AI写作】解释区块链技术的应用场景和优势
  • select 函数简介
  • CentOS Linux教程(6)--CentOS目录
  • CSS的字体属性
  • 软件测试面试题(6)——二面(游戏测试)
  • 2024年_ChatGPT 及类似的人工智能技术带来的影响与改变 怎样利用 ChatGPT 提高学习效率
  • 在SpringBoot项目中利用Redission实现布隆过滤器(布隆过滤器的应用场景、布隆过滤器误判的情况、与位图相关的操作)
  • MICS:PythonJail沙箱逃逸(持续更新中)
  • Python数据分析与可视化:从基础到高级应用
  • vue3 实现图片预览组件
  • [ABC330E] Mex and Update
  • java-重启异常断掉的线程和监控线程状态
  • Android——Application
  • 网红挣钱太容易了
  • 路由器全局配置DHCP实验简述
  • MySQL篇(视图)(持续更新迭代)
  • CANopen通讯协议笔记
  • 制作一个能对话能跳舞的otto机器人
  • SentencePiece进行文本分类
  • 大数据-147 Apache Kudu 常用 Java API 增删改查
  • 二进制位运算题
  • python库 | lxml库
  • Python_yield
  • 【项目实战】如何在项目中自定义错误码
  • VisualStudio编译时出现无法启动mt.exe
  • C++之spring
  • Codeforces Round 973 (Div. 2) C. Password Cracking
  • 抓取股票数据
  • 28岁打算转行靠谱么,这个年龄转行,有什么适合的行业么?
  • opencv滤波算法总结