这是我参与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查询结果。
扫描二维码关注公众号,回复: 13307321 查看本文章
-
StatementHandler类
StatementHandler对象主要完成两个⼯作:
-
对于JDBC的PreparedStatement类型的对象,创建的过程中,我们使⽤的是SQL语句字符串会包含若⼲个?占位符,我们其后再对占位符进⾏设值。StatementHandler通过parameterize(statement)⽅法对S tatement进⾏设值;
-
StatementHandler通过List query(Statement statement, ResultHandler resultHandler)⽅法来完成执⾏Statement,和将Statement对象返回的resultSet封装成List
介绍完相关类后,继续分析执行SQL流程,点击进入openSession()方法解析
openSession源码解析
由下图可知道openSession执行的是openSessionFromDataSource方法
进入openSessionFromDataSource中,openSession的多个重载⽅法可以指定获得的SeqSession的Executor类型和事务的处理。
默认参数介绍
方法 | 注释 |
---|---|
ExecutorType为Executor | ExecutorType为Executor的类型 |
TransactionIsolationLevel | TransactionIsolationLevel为事务隔离级别 |
autoCommit | autoCommit是否开启事务 |
selectList源码解析(举例)
点击selectList方法进入openSession中找到对应的接口类
点接selectList实现类到DefaultSqlSession类中,调用selectList的重载方法
selectList默认参数介绍
参数 | 作用 |
---|---|
statement | |
parameter | |
rowBounds | |
ResultHandler |
- configuration.getMappedStatement(statement);
根据传入的statement查询出MappedStatement对象
- executor.query(ms, wrapCollection(parameter), rowBounds, handler)
将查询出的MappedStatement对象和parameter等参数传递给executor.query方法中,委托executor类进行查询操作。
executor.query()方法解析
具体源码实现如下图所示
将Mappedstatement动态获取SQL语句,然后BoundSql封装,然后创建一级缓存,并将参数传递给query的重载方法,如下所示
如果查询的数据一级缓存中有,这直接处理,如果一级缓存中没有,则进行数据库查询,数据库查询源码如下所示:
数据库查询操作调用的是doQuery方法,然后doQuery方法结果返回后,将结果放到缓存中并返回结果
将参数都获取到后,创建JDBC的statement对象,并把statementHandler参数传递给statement对象中进行初始化操作
上述的Executor.query()⽅法⼏经转折,最后会创建⼀个StatementHandler对象,然后将必要的参数传递给StatementHandler,使⽤StatementHandler来完成对数据库的查询,最终返回List结果集。
StatementHandler.parameterize()方法解析
进入StatementHandler类的parameterize(statement)⽅法的实现
从上述的代码可以看到,StatementHandler的parameterize(Statement)⽅法调⽤了ParameterHandler的setParameters(statement)⽅法,ParameterHandler的setParameters(Statement )⽅法负责根据我们输⼊的参数,对statement对象的?占位符处进⾏赋值。
进⼊到StatementHandler的List query(Statement statement, ResultHandler resultHandler)⽅法的实现:
从上述代码我们可以看出,StatementHandler的List query(Statement statement, ResultHandlerresultHandler)⽅法的实现,是调⽤了ResultSetHandler的handleResultSets(Statement)⽅法。
ResultSetHandler.handleResultSets()方法解析
ResultSetHandler的handleResultSets(Statement)⽅法会将Statement语句执⾏后⽣成的resultSet结果集转换成List结果集
致此SQL的执行流程分析基本完成。