MyBatis源码之MyBatis中SQL语句执行过程
MyBatis源码之MyBatis中SQL语句执行过程
SQL执行入口
我们在使用MyBatis编程时有两种方式:
方式一代码如下:
SqlSession sqlSession = sqlSessionFactory.openSession();
List<Student> studentList = sqlSession.selectList("com.sjdwz.dao.StudentMapper.findAll");
方式二代码如下:
SqlSession sqlSession = sqlSessionFactory.openSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList = studentMapper.findAll();
方式一入口分析
方式一调用的是SqlSession接口的selectList方法:

执行的是DefaultSqlSession中的实现

经过多次重载后,调用的是此方法:

MappedStatement封装的是我们的SQL语句;
方法内部执行的是executor的query方法。
方法二入口分析
方法二调用的是SqlSession接口的getMapper(Class type)方法:

我们实际调用的是DefaultSqlSession实现类中的方法:


此方法内部又调用了
configuration.<T>getMapper(type, this);

最后调用了:

return mapperProxyFactory.newInstance(sqlSession);
通过工厂创建了接口的代理对象。
Mapper接口动态代理
上面讲到会通过
mapperProxyFactory.newInstance(sqlSession);
来创建动态代理类;
那创建动态代理类会执行哪些方法呢?

可以看到有MapperProxy这个类,实际上都会执行MapperProxy类中的invoke方法。

invoke方法会先判断方法是不是Object的方法,如果是,就直接调用;否则会执行cachedInvoker()方法
cachedInvoker()的作用是获取缓存中MapperMethodInvoker,如果没有则创建一个,而MapperMethodInvoker内部封装了MethodHandler。

当cacheInvoker返回了PalinMethodInvoker实例之后,紧接着调用了这个实例的PlainMethodInvoker#invoke方法

然后就调用了execute()方法

里面调用了sqlSession的方法。
方法的调用关系如下:
MapperProxy#invoke()//代理对象执行的方法,代理后所有Mapper的方法调用时,都会调用这个invoke方法
MapperProxy#cachedInvoker()//代理对象里的Method也是对象,为了避免频繁new对象,在这里给Method对象加缓存
methodCache#computeIfAbsent()//从缓存中取Method对象,取不到创建之后加入缓存
//PainMethodInvoker是MapperProxy的内部类
PlainMethodInvoker#invoke()//执行方法,所有代理对象的方法都会执行同一个。代理对象本质是方法的拦截器!
MapperMethod#execute()//执行方法,最终还是在调用SqlSession接口
SqlSession#insert()
SqlSession#update()
SqlSession#delete()
SqlSession#selectOne()
SqlSession#selectList()
SQL执行流程
查询SQL执行流程
主要步骤:
- selectOne/selectList
- SQL获取
- 参数设置
- SQL执行
- 封装结果集
调用关系如下:
DefaultSqlSession#selectOne()//执行单记录
DefaultSqlSession#selectList()//查询列表
CachingExecutor#query()
MappedStatement#getBoundSql()//获取SQL语句
CachingExecutor#query()//二级缓存查询
CachingExecutor.delegate = SimplyExecutor//装饰设计模式:Caching的对SimpleExecutor查询加二级缓存装饰
SimplyExecutor#query()
BaseExecutor#query()//子类执行查询直接调用父类方法,一级缓存
BaseExecutor#queryFromDatabase()//缓存没有则去查询数据库,一级缓存
SimplyExecutor#doQuery()//simple执行查询
SimplyExecutor#prepareStatement()//准备查询语句
RoutingStatementHandler#parameterize()//路由delegate=PreparedStatementHandler
PreparedStatementHandler#parameterize()//设置查询参数
DefaultParameterHandler#setParameters()//设置查询参数
RoutingStatementHandler#query()//路由delegate=PreparedStatementHandler
PreparedStatementHandler#query()//执行SQL,封装结果集
PreparedStatement#execute()//执行SQL查询操作
DefaultResultSetHandler#handleResultSets()//封装返回值,将查询结果封装成Object对象
增删改SQL执行流程
主要步骤
- insert|update|delete方法分析
- SQL获取
- 参数设置
- SQL执行
- 封装结果集
MyBatis中增删改的代码如下:
//DefaultSqlSession
@Override
public int insert(...) {
return update(statement, parameter);
}
@Override
public int update(String statement) {
return update(statement, null);
}
@Override
public int delete(...) {
return update(....);
}
我们发现,增删改最后执行的都是update,这是因为insert、update、delete实际上都是对数据库中数据的改变。
执行流程为:
DefaultSqlSession#update()
CachingExecutor#update()//执行更新
flushCacheIfRequired()//执行增删改前,清除对应二级缓存
CachingExecutor.delegate = SimplyExecutor//装饰模式
SimplyExecutor#update()//调用父类模板方法
BaseExecutor#update()//执行更新
BaseExecutor#clearLocalCache()//清除一级缓存,LocalCache
BaseExecutor#doUpdate()//调用子类方法
SimplyExecutor#doUpdate()//simple执行更新
SimplyExecutor#prepareStatement()//准备查询语句
RoutingStatementHandler#parameterize()//delegate=PreparedStatementHandler
PreparedStatementHandler#parameterize()//设置查询参数
DefaultParameterHandler#setParameters()//设置查询参数
RoutingStatementHandler#update()//delegate=PreparedStatementHandler
PreparedStatementHandler#update()
PreparedStatement#execute()//执行SQL,完成增删改查操作
reparedStatement#getUpdateCount()//获取影响行数
图示
最后我们画出执行的流程图如下:

MyBatis源码之MyBatis中SQL语句执行过程的更多相关文章
- 转:Oracle中SQL语句执行过程中
Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1.当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法.表名.字 ...
- mybatis源码-Mapper解析之SQL 语句节点解析(一条语句对应一个MappedStatement)
目录 一起学 mybatis 0 <sql> 节点解析 1 解析流程 2 节点解析 2.1 解析流程 2.2 <include> 节点的解析 2.3 Node.ELEMENT_ ...
- Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource
前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 首先了解下sql mapper的动态sql语法 具体的动态sql的 ...
- Spring mybatis源码篇章-Mybatis的XML文件加载
通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-Mybatis主文件加载 前话 前文主要讲解了Mybatis的主文件加载方式,本文则分析不使用主文件加载方式 ...
- html5 webDatabase 存储中sql语句执行可嵌套使用
html5 webDatabase 存储中sql语句执行可嵌套使用,代码如下: *); data.transaction(function(tx){ tx.executeSql("creat ...
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
- 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽MyBatis源码分析 - MyBatis初始化(四)之 SQL 初始化(下)
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽MyBatis源码分析 - MyBatis 的 SQL 执行过程(一)之 Executor
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- Mybatis源码解读-SpringBoot中配置加载和Mapper的生成
本文mybatis-spring-boot探讨在springboot工程中mybatis相关对象的注册与加载. 建议先了解mybatis在spring中的使用和springboot自动装载机制,再看此 ...
随机推荐
- LOTO示波器客户应用案例展示
LOTO示波器客户应用案例展示 LOTO示波器以软件功能为核心,采用独特的积木式可扩展的硬件架构,为多行业的电子电路研发工程师提供高性价比的解决方案.我们初步汇总了一些客户实测的应用案例展示如下: 1 ...
- WPF如何封装一个可扩展的Window
前言 WPF中Window相信大家都很熟悉,有时我们有一些自定义需求默认Window是无法满足的,比如在标题栏上放一些自己东西,这个时候我们就需要写一个自己的Window,实现起来也很简单,只要给Wi ...
- Scala 简单分词求和
1 package chapter07 2 3 object Test17_CommonWordCount { 4 def main(args: Array[String]): Unit = { 5 ...
- #轮廓线dp,模型转换#洛谷 3226 [HNOI2012]集合选数
题目 问有多少个集合 \(S\) 是 \([1,n]\) 的子集, 并且 \(\forall a,b\in S,a|b\),满足 \(\frac{b}{a}\neq \{2,3\}\) 分析 可以发现 ...
- OpenHarmony使用ArkUI Inspector分析布局
本文转载自<#2023 盲盒+码 # OpenHarmony使用ArkUI Inspector分析布局>,作者:zhushangyuan_ OpenHarmony使用ArkUI Ins ...
- OpenHarmony Liteos_A内核之iperf3移植心得
一.iperf3工作原理 iperf3主要的功能是测试基于特定路径的带宽,在客户端和服务器端建立连接(三次握手)后,客户端发送一定大小的数据报并记下发送的时间,或者客户端在一定的时间内发送数据并记下发 ...
- 在Centos 8 服务器用tmux多开窗口
在 CentOS 服务器上使用 tmux 来多开窗口是一个高效的方式.tmux 是一个终端复用器,它允许你在一个终端窗口中打开多个终端会话,还可以在会话之间轻松切换,非常适合长时间运行程序或多任务操作 ...
- 十城百校联动!HDC.Together 2023 HarmonyOS学生公开课与千余名校园学子见证鸿蒙力量
8月6日,HDC.Together2023 HarmonyOS学生公开课在东莞松山湖举办.有来自清华大学.北京大学.哈尔滨工业大学等全国百余所高校,千余名学生开发者齐聚会场,与华为高级技术专家.生 ...
- nginx 均衡负载
前言 在此只介绍一些nginx的简单的负载均衡. 正文 在这篇之前,请看我的nginx反向代理这一篇,是接着上面的例子写的. 我在上个例子中,分别是两个a.html 和 b.html 现在我把他们的名 ...
- 安装 php_mongodb.dll的坑
背景 php_mongodb.dll在这里介绍的是for php,php_mongodb.dll是这个坑,因为php_mongodb.dll前生是php_mongo.dll,而这个东西,它又不更新了, ...