Mybatis Sql 执行全链路, 跟踪返回结果

tech2024-10-11  38

01、前言

根据 Mybatis SQL 执行流程图进一步了解

02、Mybatis Sql 的执行过程

大致可以分为以下几步操作:

📖 在前面的内容中, 知道了 Mybatis Mapper 是动态代理的实现, 查看 SQL 执行过程, 就需要紧跟实现了 InvocationHandler 的 MapperProxy 类

03、执行增删改查

@Select(" SELECT * FROM SUBJECT WHERE ID = #{id}") PrimitiveSubject getSubject(@Param("id") final int id);

我们以上述方法举例, 调用方通过 SqlSession 获取 Mapper 动态代理对象, 执行 Mapper 方法时会通过 InvocationHandler 进行代理

在 MapperMethod#execute 中, 根据 MapperMethod -> SqlCommand -> SqlCommandType 来确定增、删、改、查方法

📖 SqlCommandType 是一个枚举类型, 对应五种类型 UNKNOWN、INSERT、UPDATE、DELETE、SELECT、FLUSH

04、参数处理

查询操作对应 SELECT 枚举值, if else 中判断为返回值是否集合、无返回值、单条查询等, 这里以查询单条记录作为入口

Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param);

📖 这里能够解释一个之前困扰我的问题, 那就是为什么方法入参只有单个 @Param("id"), 但是参数 param 对象会存在两个键值对

继续查看 SqlSession#selectOne 方法, sqlSession 是一个接口, 具体还是要看实现类 DefaultSqlSession

因为单条和查询多条以及分页查询都是走的一个方法, 所以在查询的过程中, 会将分页的参数进行添加

05、执行器处理

在 Mybatis 源码中, 创建的执行器默认是 CachingExecutor, 使用了装饰者模式, 在类中保持了 Executor 接口的引用, CachingExecutor 在持有的执行器基础上增加了缓存的功能

delegate.query 就是在具体的执行器了, 默认 SimpleExecutor, query 方法统一在抽象父类 BaseExecutor 中维护

BaseExecutor#queryFromDatabase 方法执行了缓存占位符以及执行具体方法, 并将查询返回数据添加至缓存

BaseExecutor#doQuery 方法是由具体的 SimpleExecutor 实现

06、执行 SQL

因为我们 SQL 中使用了参数占位符, 使用的是 PreparedStatementHandler 对象, 执行预编译SQL的 Handler, 实际使用 PreparedStatement 进行 SQL 调用

07、返回数据解析

将 JDBC 返回类型转换为 Java 类型, 根据 resultSets 和 resultMap 进行转换

最新回复(0)