欢迎光临
我们一直在努力

一条 SQL 在 MyBatis 里到底经历了什么?

一条 SQL 在 MyBatis 里到底经历了什么?

上一篇我们讲了:

MyBatis 为什么知道该执行哪条 SQL?

核心答案是:

Mapper方法

MappedStatement

MyBatis 在启动时已经建立好了映射关系。

但是新的问题来了。

找到 SQL 只是第一步。真正执行 SQL 的过程又是怎样的?

例如:

User user = userMapper.selectById(1L);

看起来只有一行代码。

但实际上。

从 Mapper 到数据库,中间经过了很多组件。

今天我们就把这条链路彻底看明白。


从 Mapper 开始

执行:

userMapper.selectById(1L);

首先进入:

MapperProxy

上一篇已经讲过。

Mapper 本质上是动态代理对象。

最终会进入:

MapperProxy.invoke()

这里会找到对应的:

MapperMethod

然后执行:

mapperMethod.execute(sqlSession, args);

接下来正式进入 MyBatis 核心执行流程。


SqlSession 登场

很多人学 MyBatis 时。

最容易忽略的其实是:

SqlSession

但实际上。

它才是真正的执行入口。

例如:

sqlSession.selectOne(...)

sqlSession.insert(...)

sqlSession.update(...)

Mapper 最终也是调用它。

所以:

Mapper

SqlSession

这是第一层关系。


真正执行 SQL 的是谁?

很多人以为:

SqlSession

直接操作数据库,其实不是。

继续往下会进入:

Executor

源码:

executor.query(...)

这里出现了 MyBatis 最重要的组件之一:

Executor

你可以把它理解成:

SQL 执行总管


Executor 到底负责什么?

它主要负责:

缓存处理、SQL执行、事务管理、结果返回

无论:

select
insert
update
delete

最终都会走到:

Executor

所以:

SqlSession

Executor

是 MyBatis 执行链路最核心的一层。


Executor 会直接操作 JDBC 吗?

还是不会,继续往下,会进入:

StatementHandler

很多人第一次看到这个类名。

会觉得很普通,实际上非常关键。

因为 JDBC 的核心对象就是:

Statement

PreparedStatement

而:

StatementHandler

就是专门处理这些对象的。


SQL 是什么时候变成 PreparedStatement 的?

假设 Mapper 中写:

<select id="selectById">
select * from user where id = #{id}
</select>

此时 SQL 还是:

select * from user where id = #{id}

进入:

StatementHandler

以后。

MyBatis 会处理成:

select * from user where id = ?

然后创建:

PreparedStatement

准备执行。


参数是谁设置进去的?

新的问题又来了。

既然变成:

select * from user where id = ?

那:

1L

怎么放进去?这里会进入:

ParameterHandler

负责参数绑定。

例如:

ps.setLong(1,1L);

最终变成:

select * from user where id = 1

准备发送数据库


数据库返回结果以后呢?

执行完成后。

数据库返回:

ResultSet

例如:

id=1
name=Tom
age=18

但是业务代码需要的是:

User

对象。

于是进入:

ResultSetHandler

负责结果映射。

把:

ResultSet

转换成:

User

对象。

最终返回给业务代码。


整个执行链路

现在把所有组件串起来。

执行:

userMapper.selectById(1L);

实际流程:

MapperProxy

MapperMethod

SqlSession

Executor

StatementHandler

ParameterHandler

JDBC

Database

ResultSet

ResultSetHandler

User对象

这才是一条 SQL 完整的生命周期。


为什么要拆这么多组件?

很多人第一次看源码会觉得:

太复杂了

直接一个类执行完不行吗?

当然可以,但扩展性会很差。

MyBatis 的设计思想是:

一个组件只负责一件事

例如:

Executor负责执行

StatementHandler负责SQL

ParameterHandler负责参数

ResultSetHandler负责结果

以后要扩展,只需要替换对应组件即可。

这也是后面插件机制能够实现的基础。


真正的核心是谁?

如果只保留一个组件。

那一定是:

Executor

因为:

SqlSession是门面

StatementHandler是工具

ParameterHandler是辅助

ResultSetHandler是辅助

而:

Executor

才是真正控制整个 SQL 执行过程的人。

后面缓存机制、插件机制、事务机制。

本质上也都是围绕 Executor 展开的。


总结

执行:

userMapper.selectById(1L);

看起来只是一个普通方法调用。

实际上经历了完整执行链路:

MapperProxy

SqlSession

Executor

StatementHandler

ParameterHandler

数据库

ResultSetHandler

Java对象

所以:

一条 SQL 在 MyBatis 里并不是直接执行的,而是经过多个组件协同完成。

而整个链路的核心。

就是:

Executor

理解了它,就理解了 MyBatis 执行流程的核心。


上一篇:

《MyBatis 为什么知道该执行哪条 SQL?》

下一篇:

《查询结果为什么能自动变成 Java 对象?》

赞(0)
未经允许不得转载:171主机测评 » 一条 SQL 在 MyBatis 里到底经历了什么?
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址