一文带你掌握Mybatis框架执行SQL流程源码

这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

Mybatis执行SQL流程源码解析

首先,先介绍一下相关类

SqlSession

  • SqlSession是一个接口,他有两个实现类:DefaultSqlSession(默认实现类)、SqlSessionManager(已经弃用)。

  • SqlSession是Mybatis中用于和数据库交互的顶层类,通常将它和ThreadLocal一起绑定,一个会话使用一个SqlSession,因为SqlSession是线程不安全的,所以使用玩SqlSession后需要close,关闭SqlSession。

public class DefaultSqlSession implements SqlSession {

  private final Configuration configuration;
  private final Executor executor;
}
复制代码
  • SqlSession中有两个最重要的参数,configuration与初始化时相同,Executor是执行器。

    SqlSession在任务方法的执行过程中,会把任务委派给Executor进行处理

Executor

  • Executor也是一个接口,他有三个常⽤的实现类

    • BatchExecutor (重⽤语句并执⾏批量更新)
    • ReuseExecutor (重⽤预处理语句prepared statements)
    • SimpleExecutor (普通的执⾏器,默认)
  • Executor作用

    • 1、根据传递的参数,完成SQL语句的动态解析,⽣成BoundSql对象,StatementHandler使⽤;

    • 2、为查询创建缓存,以提⾼性能

    • 3、创建JDBC的Statement连接对象,传递给StatementHandler对象,返回List查询结果。

StatementHandler类

StatementHandler对象主要完成两个⼯作:

  • 对于JDBC的PreparedStatement类型的对象,创建的过程中,我们使⽤的是SQL语句字符串会包含若⼲个?占位符,我们其后再对占位符进⾏设值。StatementHandler通过parameterize(statement)⽅法对S tatement进⾏设值;

  • StatementHandler通过List query(Statement statement, ResultHandler resultHandler)⽅法来完成执⾏Statement,和将Statement对象返回的resultSet封装成List

介绍完相关类后,继续分析执行SQL流程,点击进入openSession()方法解析

openSession源码解析

image.png

由下图可知道openSession执行的是openSessionFromDataSource方法

image.png

进入openSessionFromDataSource中,openSession的多个重载⽅法可以指定获得的SeqSession的Executor类型和事务的处理。

默认参数介绍

方法 注释
ExecutorType为Executor ExecutorType为Executor的类型
TransactionIsolationLevel TransactionIsolationLevel为事务隔离级别
autoCommit autoCommit是否开启事务

image.png

selectList源码解析(举例)

image.png

点击selectList方法进入openSession中找到对应的接口类

image.png

点接selectList实现类到DefaultSqlSession类中,调用selectList的重载方法

image.png

selectList默认参数介绍

参数 作用
statement
parameter
rowBounds
ResultHandler
  • configuration.getMappedStatement(statement);

根据传入的statement查询出MappedStatement对象

  • executor.query(ms, wrapCollection(parameter), rowBounds, handler)

将查询出的MappedStatement对象和parameter等参数传递给executor.query方法中,委托executor类进行查询操作。

executor.query()方法解析

具体源码实现如下图所示

image.png

将Mappedstatement动态获取SQL语句,然后BoundSql封装,然后创建一级缓存,并将参数传递给query的重载方法,如下所示

image.png

如果查询的数据一级缓存中有,这直接处理,如果一级缓存中没有,则进行数据库查询,数据库查询源码如下所示:

image.png

数据库查询操作调用的是doQuery方法,然后doQuery方法结果返回后,将结果放到缓存中并返回结果

image.png

将参数都获取到后,创建JDBC的statement对象,并把statementHandler参数传递给statement对象中进行初始化操作

image.png

image.png

上述的Executor.query()⽅法⼏经转折,最后会创建⼀个StatementHandler对象,然后将必要的参数传递给StatementHandler,使⽤StatementHandler来完成对数据库的查询,最终返回List结果集。

StatementHandler.parameterize()方法解析

进入StatementHandler类的parameterize(statement)⽅法的实现

image.png

image.png

从上述的代码可以看到,StatementHandler的parameterize(Statement)⽅法调⽤了ParameterHandler的setParameters(statement)⽅法,ParameterHandler的setParameters(Statement )⽅法负责根据我们输⼊的参数,对statement对象的?占位符处进⾏赋值。

进⼊到StatementHandler的List query(Statement statement, ResultHandler resultHandler)⽅法的实现:

image.png

从上述代码我们可以看出,StatementHandler的List query(Statement statement, ResultHandlerresultHandler)⽅法的实现,是调⽤了ResultSetHandler的handleResultSets(Statement)⽅法。

ResultSetHandler.handleResultSets()方法解析

ResultSetHandler的handleResultSets(Statement)⽅法会将Statement语句执⾏后⽣成的resultSet结果集转换成List结果集

image.png

image.png

致此SQL的执行流程分析基本完成。

猜你喜欢

转载自juejin.im/post/7033564472253874189