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

【Mytais系列】Select语句执行流程

以下是通过 时序图文字说明 详细描述的 MyBatis 执行一条 SELECT 语句的完整流程,包括缓存查询、数据库访问和结果返回的各个环节:


时序图(Sequence Diagram)


详细执行流程解析

1. 客户端发起查询请求
  • 客户端调用 SqlSession 的查询方法(如 selectOne),传入 SQL 语句的标识(如 selectUserById)和参数(如 id=1)。
2. 二级缓存检查(CachingExecutor)
  • CachingExecutor 作为装饰器,优先检查 二级缓存(对应 Mapper 级别的缓存):
    • 若命中,直接返回缓存结果(流程结束)。
    • 若未命中,继续委托给底层 Executor(如 SimpleExecutorBatchExecutor)处理。
3. 一级缓存检查(BaseExecutor)
  • BaseExecutor 负责处理 一级缓存(当前 SqlSession 的缓存):
    • 若命中,返回缓存结果。
    • 若未命中,继续执行数据库查询。
4. 数据库查询
  • 4.1 创建 PreparedStatement
    StatementHandler 通过 Connection 创建 PreparedStatement 对象。
  • 4.2 参数绑定
    ParameterHandler 将参数(如 id=1)绑定到 SQL 中的占位符(?)。
  • 4.3 执行 SQL
    通过 JDBC 驱动执行 SQL,向数据库发送查询请求。
  • 4.4 结果映射
    ResultSetHandler 将返回的 ResultSet 转换为 Java 对象(如 User 对象)。
5. 缓存更新
  • 一级缓存更新
    查询结果立即存入当前 SqlSession 的一级缓存(localCache)。
  • 二级缓存更新
    SqlSession 执行了 commit()close(),且二级缓存已开启(<cache/> 配置),则结果会同步到二级缓存。
6. 结果返回
  • 最终结果通过 SqlSession 返回给客户端。

关键组件作用

组件

职责

SqlSession

用户操作 MyBatis 的入口,封装了会话状态和数据库操作。

Executor

执行器,负责缓存查询和 SQL 执行(分为 SimpleExecutorReuseExecutor 等)。

CachingExecutor

装饰器模式实现,添加二级缓存逻辑。

StatementHandler

处理 SQL 语句(创建 PreparedStatement)。

ParameterHandler

绑定 SQL 参数。

ResultSetHandler

处理结果集(映射为 Java 对象)。

JDBC Driver

实际执行数据库操作。


缓存与数据库访问的优先级

  1. 二级缓存(跨会话共享) → 2. 一级缓存(当前会话) → 3. 数据库
    • 若二级缓存未命中,但一级缓存命中,结果会直接返回,不会更新二级缓存
    • 二级缓存的更新需等待会话提交或关闭。

示例场景

场景 1:首次查询(无缓存)
// 1. 客户端发起查询
User user = sqlSession.selectOne("selectUserById", 1);// 执行流程:
// 二级缓存未命中 → 一级缓存未命中 → 查询数据库 → 结果存入一级缓存
// 提交后同步到二级缓存
sqlSession.commit();
场景 2:同一会话重复查询
// 第一次查询(查数据库)
User user1 = sqlSession.selectOne("selectUserById", 1);// 第二次查询(命中一级缓存)
User user2 = sqlSession.selectOne("selectUserById", 1);
场景 3:跨会话查询(二级缓存生效)
// Session1 查询并提交
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("selectUserById", 1);
session1.commit();  // 同步到二级缓存
session1.close();// Session2 查询(命中二级缓存)
SqlSession session2 = sqlSessionFactory.openSession();
User user2 = session2.selectOne("selectUserById", 1); 

注意事项

  1. 缓存一致性
    • 更新操作(INSERT/UPDATE/DELETE)会清空一级缓存(当前会话)和二级缓存(全局)。
  1. 事务提交
    • 未提交的会话中,二级缓存不会更新。
  1. 序列化要求
    • 二级缓存的对象需实现 Serializable 接口。
  1. 性能权衡
    • 高频写入场景下,建议关闭二级缓存,避免频繁缓存失效。

总结

MyBatis 的 SELECT 执行流程通过 二级缓存 → 一级缓存 → 数据库 的优先级策略,最大化利用缓存提升性能。理解其内部组件协作(如 ExecutorStatementHandler)和缓存更新机制,有助于优化数据访问层设计,平衡性能与数据一致性。

http://www.xdnf.cn/news/3700.html

相关文章:

  • 学习笔记:Qlib 量化投资平台框架 — FOR DEVELOPERS
  • 使用线性表实现通讯录管理
  • MySQL表的约束
  • Yocto介绍
  • 【C语言练习】018. 定义和初始化结构体
  • 【c++】模板详解
  • [android]MT6835 Android 移植brctl指令
  • PowerShell从5.1升级到7.X
  • 深挖Java之:运算符与输入器
  • #Paper Reading# DeepSeek-R1
  • DeepSeek与MySQL:开启数据智能新时代
  • Java SE(7)——类和对象(二)
  • 【Java Stream流-59】Java Stream流式编程:高效、优雅的数据处理之道
  • [案例二] 菜单条制作(Menuscript)与工具条制作(Toolbar)
  • Python基础语法
  • 【Arthas】火焰图优化应用CPU(问题原因:获取调用栈)
  • C语言字符函数和字符串函数详解:从基础到实战
  • C语言奇幻指南:宏、头文件与变量的秘密世界
  • 二、机器学习中Python变量基础
  • 防范反序列化攻击:如何安全处理敏感数据序列化
  • 【C/C++】MQTT
  • Git从入门到精通-第三章-获取Git仓库
  • 【Agent搭建】利用coze平台搭建一个AI销售?
  • Spring MVC @RequestBody 注解怎么用?接收什么格式的数据?
  • 重载和覆写有什么区别?
  • 18、状态库:中央魔法仓库——React 19 Zustand集成
  • STM32基础教程——软件I2C
  • 力扣-字符串-165 比较版本号
  • 【算法基础】递归算法 - JAVA
  • C++ STL vector容器详解:从原理到实践