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

MyBatis 执行流程详解:一级缓存与二级缓存深度解析

MyBatis 是一个优秀的持久层框架,它不仅简化了数据库操作,还提供了强大的缓存机制来提升查询性能。本文将深入探讨 MyBatis 的执行流程,并重点分析一级缓存和二级缓存的实现原理及其使用场景。

1. MyBatis 执行流程

MyBatis 的执行流程可以分为以下几个步骤:

1.1 加载配置文件

MyBatis 首先加载 SqlMapConfig.xml 配置文件,该文件包含了数据库连接信息、事务管理器配置、映射文件路径等。SqlMapConfig.xml 是 MyBatis 的核心配置文件,所有的全局配置都在这里定义。

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/qcby/dao/UserMapper.xml"/>
    </mappers>
</configuration>

1.2 创建 SqlSessionFactory

通过 SqlSessionFactoryBuilder 构建 SqlSessionFactory 对象,该对象是 MyBatis 的核心对象,用于创建 SqlSession

InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

1.3 创建 SqlSession

SqlSession 是 MyBatis 与数据库交互的会话对象,它提供了执行 SQL 语句、管理事务、获取映射器等方法。

SqlSession sqlSession = sqlSessionFactory.openSession();

1.4 执行 SQL 语句

通过 SqlSession 执行 SQL 语句,MyBatis 会根据映射文件(XXXMapper.xml)中的配置,将 SQL 语句与 Java 对象进行映射。

UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.findById(1);

1.5 提交或回滚事务

根据业务逻辑,决定是否提交或回滚事务。

sqlSession.commit(); // 提交事务
sqlSession.rollback(); // 回滚事务

1.6 关闭 SqlSession

操作完成后,关闭 SqlSession 以释放资源。

sqlSession.close();

2. MyBatis 缓存机制

MyBatis 提供了两级缓存机制:一级缓存二级缓存,用于提高数据库查询的性能。

2.1 一级缓存

一级缓存是 SqlSession 级别的缓存,默认开启。当 SqlSession 执行查询操作时,查询结果会被缓存到一级缓存中。如果再次执行相同的查询,MyBatis 会直接从缓存中获取结果,而不需要再次访问数据库。

一级缓存的生命周期与 SqlSession 相同,当 SqlSession 关闭时,一级缓存也会被清空。

SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user1 = userDao.findById(1);
User user2 = userDao.findById(1);
System.out.println(user1 == user2); // true,因为第二次查询从一级缓存中获取
sqlSession.close();
一级缓存失效的情况
  • SqlSession 不同:不同的 SqlSession 无法共享一级缓存。

  • 查询条件不同:即使 SqlSession 相同,查询条件不同也会导致缓存失效。

  • 执行了增删改操作:在两次查询之间执行了增删改操作,会导致一级缓存失效。

  • 手动清除缓存:调用 sqlSession.clearCache() 方法可以手动清除一级缓存。

2.2 二级缓存

二级缓存是 Mapper 级别的缓存,多个 SqlSession 可以共享同一个二级缓存。二级缓存默认关闭,需要在映射文件中手动开启。

开启二级缓存的条件
  1. 在核心配置文件中开启二级缓存

<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>
  1. 在映射文件中声明使用二级缓存

<mapper namespace="com.qcby.dao.UserDao">
    <cache/>
</mapper>
  1. 实体类实现序列化接口

public class User implements Serializable {
    private Integer id;
    private String username;
    // getter 和 setter 方法
}
  1. SqlSession 关闭或提交后生效:二级缓存的数据在 SqlSession 关闭或提交后才会写入缓存。

二级缓存失效的情况
  • 执行了增删改操作:在两次查询之间执行了增删改操作,会导致二级缓存失效。

二级缓存的配置

二级缓存可以通过 <cache> 标签进行配置,常用的配置参数包括:

  • eviction:缓存回收策略,默认是 LRU(最近最少使用)。

  • flushInterval:缓存刷新间隔,单位为毫秒。

  • size:缓存对象的最大数量。

  • readOnly:缓存是否只读,默认为 false

<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

2.3 缓存查询顺序

MyBatis 的缓存查询顺序如下:

  1. 先查询二级缓存:因为二级缓存中可能会有其他 SqlSession 查询出来的数据,可以直接拿来使用。

  2. 如果二级缓存未命中,再查询一级缓存

  3. 如果一级缓存也没有命中,则查询数据库

当 SqlSession 关闭时,一级缓存的数据会写入二级缓存。

3. 总结

MyBatis 提供了强大的缓存机制,能够有效提高数据库查询的性能。一级缓存是 SqlSession 级别的缓存,适用于单次会话中的重复查询;二级缓存是 Mapper 级别的缓存,适用于多个会话之间的共享数据。通过合理使用缓存,可以减少数据库的访问压力,提升系统的整体性能。

通过本文,你应该对 MyBatis 的执行流程、一级缓存和二级缓存有了更深入的理解。希望这些内容能帮助你在实际项目中更好地使用 MyBatis。


 

 

 

参考文献:

  • MyBatis 官方文档

  • MyBatis 缓存机制详解

相关推荐:

  • 深入理解 MyBatis 源码

  • MyBatis 高级用法

相关文章:

  • QT并发编程进阶--线程安全与同步技巧详解
  • css-grid布局
  • 日期类的实现
  • 基于复杂的商业和政策信息构建GraphRAG,并结合通义千问大模型进行问答的应用场景
  • 美团Leaf分布式ID实战:深入解析雪花算法原理与应用
  • 网络空间安全(38)Windows/Linux权限
  • 算法刷题记录——LeetCode篇(1) [第1~100题](持续更新)
  • yarn install 出现certificate has expired报错问题
  • 读博士论文(未完待续)
  • (九)Dart 中的 Map(映射)
  • FPGA设计中时间单位科普
  • VS Code使用过程记录
  • Redisson 分布式锁原理
  • MCP(1)
  • 深入解析 Redis 原理:架构、数据结构与高效存储
  • 动态规划(6.不同路径II)
  • Binder机制源码分析
  • 蓝桥杯关于字符串的算法题目(leetcode回文串的判断问题)
  • 【队列】循环顺序队列和链式队列
  • 传感器研习社:臭味传感器(Odorant Sensor)
  • 华住集团:第一季度盈利8.94亿元,同比增长超三成
  • 我国成功发射中星3B卫星
  • 短剧植入,撬不动96.4%直男的钱包 | 调研报告
  • 金爵奖主竞赛单元评委名单公布,中国评委有黄渤、咏梅等人
  • 今晚油价下调,加满一箱油将省9元
  • 武汉警方通报一起故意伤害案件:1人死亡,嫌疑人已被抓获