Skip to content
MyBatis 核心执行链路 · 第 1 篇 / 共 3 篇
领域编程与框架
专题MyBatis 专题
当前序列MyBatis 核心执行链路
阅读位置第 1 篇 / 共 3 篇当前专题第 1 个序列 / 共 3 个序列

MyBatis 的 Mapper、Executor 和 SQL 执行链路

先说结论

  • Mapper 本身只是接口入口,真正执行 SQL 的核心在 Executor
  • 一次 MyBatis 调用会依次经过 Mapper 代理、MappedStatement、参数处理、Statement 执行和结果映射
  • 真正排障时,很多问题都能归到三层:SQL 本身、执行器行为、映射结果

一、先把三个角色分清楚

1. Mapper

Mapper 更像“DAO 的声明式门面”。
你调用 userMapper.selectById(1) 时,并不是接口自己有实现,而是 MyBatis 给它生成了代理对象。

2. MappedStatement

这是 MyBatis 对一条 SQL 的完整描述,里面会保存:

  • SQL 来源
  • 入参映射
  • 返回值映射
  • 执行类型
  • 缓存配置

可以把它理解成“这条 SQL 的运行说明书”。

3. Executor

Executor 是真正干活的执行器。
它负责:

  • 调一级缓存
  • 创建 StatementHandler
  • 执行查询或更新
  • 返回结果

常见实现里,最常见的是 SimpleExecutorReuseExecutorBatchExecutor

二、一次查询大致会经过什么

以一个普通 select 为例,链路大致是:

  1. 调用 Mapper 接口方法。
  2. 代理对象定位到对应的 MappedStatement
  3. MyBatis 根据参数构造 BoundSql
  4. Executor 创建 StatementHandler。
  5. StatementHandler 负责预编译、设参、执行。
  6. ResultSetHandler 把结果集映射成对象。
  7. 返回给调用方,并视情况写入一级缓存。

这条链路一旦理顺,后面很多问题就不再神秘,比如:

  • 为什么同一个会话里查两次可能不走库
  • 为什么批量写和普通写行为不同
  • 为什么动态 SQL 最后能生成一条完整 SQL

三、Executor 到底有什么区别

1. SimpleExecutor

每次执行都新建 Statement,简单直接,最容易理解。

2. ReuseExecutor

会复用 Statement,适合 SQL 模板重复较多的场景,但收益通常没有很多人想象得那么大。

3. BatchExecutor

适合批量更新、批量插入。
它真正的价值在于减少网络往返和数据库交互次数,但也会带来:

  • 错误定位更靠后
  • 事务边界更敏感
  • 批量失败处理更复杂

四、平时最容易在哪几层出问题

1. SQL 和参数层

比如:

  • 动态 SQL 拼错
  • 参数名不一致
  • #{} / ${} 用错

2. 执行器与缓存层

比如:

  • 一级缓存导致“为什么刚更新完又查到旧值”
  • 批处理没及时 flush
  • 不同 SqlSession 行为不一致

3. 结果映射层

比如:

  • 字段名和属性名对不上
  • 嵌套结果映射导致对象结构异常
  • 返回多行却只接单对象

五、排查时更实用的顺序

如果线上发现 MyBatis 行为不符合预期,我更建议按这个顺序看:

  1. 先看最终 SQL 是什么。
  2. 再看参数有没有正确绑定。
  3. 再看是不是执行器、缓存或批处理行为影响了结果。
  4. 最后看结果映射是不是把数据“接错了”。

很多时候不是 MyBatis 太复杂,而是没先把问题落到正确层级。

总结

MyBatis 的 Mapper、Executor 和 SQL 执行链路可以简单理解成:Mapper 负责入口,MappedStatement 负责描述,Executor 负责执行。只要把这三层分清,后面无论是查缓存、看批处理,还是排查结果映射问题,都会顺很多。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读MyBatis 动态 SQL 怎么写更稳适合把 Mapper、Executor、动态 SQL 和缓存机制放在一起理解。MyBatis 专题 · MyBatis 核心执行链路同一序列 · 顺着当前主线继续读MyBatis 一级缓存和二级缓存怎么理解适合把 Mapper、Executor、动态 SQL 和缓存机制放在一起理解。MyBatis 专题 · MyBatis 核心执行链路同专题其他序列 · 共享标签:MySQLMyBatis 批处理写入怎么控制内存和事务适合把缓存、结果映射、动态 SQL 和批处理写入放在一条持久层实现主线上看。MyBatis 专题 · MyBatis 查询组织与批处理控制同专题其他序列 · 共享标签:MySQLMyBatis 批量写入和事务边界适合把分页、N+1 和批处理边界放到一起看。MyBatis 专题 · MyBatis 性能与写入治理跨专题关联 · 同场景:基础学习聚合根和事务边界怎么划分适合把 DDD、Saga、TCC 和 BFF、网关边界放在一起看。架构与设计专题 · 分布式系统取舍与边界跨专题关联 · 同场景:基础学习冷热分层和索引生命周期怎么设计适合把 refresh、merge、冷热分层和批量写入放到一起看。Elasticsearch 专题 · Elasticsearch 写入与分层架构
继续阅读MyBatis 核心执行链路当前序列第 1 篇 / 共 3 篇当前专题第 1 个序列 / 共 3 个序列
往前看
上一序列分布式系统取舍与边界从第 1 篇开始:聚合根和事务边界怎么划分
往后看
下一篇MyBatis 动态 SQL 怎么写更稳继续当前序列下一章下一序列MyBatis 性能与写入治理从第 1 篇开始:MyBatis 分页插件和 Count 优化

把零散经验整理成可查、可复用、可持续更新的企业级知识门户