MyBatis(12) 源码解析之SQL执行流程

一、前言

资料

  1. mybatis文档:https://mybatis.org/mybatis-3/index.html
  2. mybatis源码:https://github.com/mybatis/mybatis-3

二、mybatis是什么?

  1. 一款优秀的持久层框架,支持自定义SQL存储过程以及高级映射
  2. 免除了传统的JDBC代码以及设置参数获取结果集的工作。
  3. 可以通过XML/注解方式来配置和映射 原始类型接口Java POJO为数据库中的记录。

mybatis和hibernate都属于ORM框架

ORM是什么?

ORM对象关系映射: 用于实现面向对象编程语言里不同类型系统数据之间的转换,解决数据库与程序间的异构性

ex: username字段在数据库中为VARCHAR类型,而在Java对象中为String类型
MyBatis(12) 源码解析之SQL执行流程_第1张图片

三、入门环境准备

这里可直接参考mybatis文档:https://mybatis.org/mybatis-3/getting-started.html

小编这里使用的是mybatis源码环境,即 将源码clone下来根据文档入门实现了一个简单的sql查询

详细代码可自行参考: https://gitee.com/zhengqingya/java-workspace

MyBatis(12) 源码解析之SQL执行流程_第2张图片
MyBatis(12) 源码解析之SQL执行流程_第3张图片
MyBatis(12) 源码解析之SQL执行流程_第4张图片


下面将通过debug一步一步探索源码,主要将围绕如图3大模块来debug

MyBatis(12) 源码解析之SQL执行流程_第5张图片

四、mybatis获取数据源

MyBatis(12) 源码解析之SQL执行流程_第6张图片
MyBatis(12) 源码解析之SQL执行流程_第7张图片
这里的root即拿到的配置文件中的内容,然后一个一个去解析加载数据
MyBatis(12) 源码解析之SQL执行流程_第8张图片
propertiesElement(root.evalNode("properties")):加载jdbc.properties配置文件中数据
MyBatis(12) 源码解析之SQL执行流程_第9张图片
执行完,到environmentsElement(root.evalNode("environments"))方法处,即已经拿到我们配置文件的数据源信息
MyBatis(12) 源码解析之SQL执行流程_第10张图片
然后进入dataSourceElement(child.evalNode("dataSource"))
MyBatis(12) 源码解析之SQL执行流程_第11张图片
再进入resolveClass,发现通过pooled这个key可以拿到org.apache.ibatis.datasource.pooled.PooledDataSourceFactory
MyBatis(12) 源码解析之SQL执行流程_第12张图片
回来我们可以发现获取到的这个pooled值value,也就是org.apache.ibatis.datasource.pooled.PooledDataSourceFactoryClass类再newInstance拿到DataSourceFactory这么一个实例

DataSourceFactory factory = (DataSourceFactory) resolveClass(type).getDeclaredConstructor().newInstance();

最终返回,即发现已经拿到了我们的dataSource数据库源,然后通过Builder设计模式赋值给Environment,存放到org.apache.ibatis.session.Configuration#environment
MyBatis(12) 源码解析之SQL执行流程_第13张图片

五、mybatis获取sql执行语句

首先要明白我们的sql语句是写在mapper.xml中,然后是在mybatis-config.xml中解析,因此debug 查看org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration 方法中的 mapperElement(root.evalNode("mappers"))
MyBatis(12) 源码解析之SQL执行流程_第14张图片
这里因为只有resource,因此走如下断点处方式解析mapper
MyBatis(12) 源码解析之SQL执行流程_第15张图片
进入mapperParser.parse()
MyBatis(12) 源码解析之SQL执行流程_第16张图片
这里因此我们的sql是select语句,因此直接进入buildStatementFromContext(context.evalNodes("select|insert|update|delete"))
MyBatis(12) 源码解析之SQL执行流程_第17张图片
注意此时list中的就是我们mapper中的sql语句
MyBatis(12) 源码解析之SQL执行流程_第18张图片
然后进入statementParser.parseStatementNode()看看mybatis拿到sql内容之后又是怎么做的呢

可以看见mybatis是将context中的sql内容一个一个解析成临时的局部变量
MyBatis(12) 源码解析之SQL执行流程_第19张图片
再走到下面,发现解析的变量是在这里被使用,因此进入builderAssistant.addMappedStatement(...)方法
MyBatis(12) 源码解析之SQL执行流程_第20张图片
最终可以看见这些变量是存到了MappedStatement类中,然后传给org.apache.ibatis.session.Configuration#mappedStatements
MyBatis(12) 源码解析之SQL执行流程_第21张图片

六、mybatis操作数据库

MyBatis(12) 源码解析之SQL执行流程_第22张图片
进入configuration.newExecutor(tx, execType)
MyBatis(12) 源码解析之SQL执行流程_第23张图片
这里可以看见默认返回一个SimpleExecutor简单执行器,以及我们的mybatis在这里默认开启一级缓存
MyBatis(12) 源码解析之SQL执行流程_第24张图片
执行完这里会返回一个DefaultSqlSession
MyBatis(12) 源码解析之SQL执行流程_第25张图片
然后调用selectOne方法
MyBatis(12) 源码解析之SQL执行流程_第26张图片
进入selectList
MyBatis(12) 源码解析之SQL执行流程_第27张图片
这里ms中含之前获取的sql执行语句,然后进入executor.query
MyBatis(12) 源码解析之SQL执行流程_第28张图片
MyBatis(12) 源码解析之SQL执行流程_第29张图片
MyBatis(12) 源码解析之SQL执行流程_第30张图片
这里可以看见prepareStatement方法中拿到我们的connection
MyBatis(12) 源码解析之SQL执行流程_第31张图片
然后进入handler.query(stmt, resultHandler)可以看到拿到了PreparedStatement
MyBatis(12) 源码解析之SQL执行流程_第32张图片
然后进入resultSetHandler.handleResultSets(ps)
MyBatis(12) 源码解析之SQL执行流程_第33张图片
进入getFirstResultSet(stmt)方法
MyBatis(12) 源码解析之SQL执行流程_第34张图片
进入ResultSetWrapper
MyBatis(12) 源码解析之SQL执行流程_第35张图片
到这里我们就可以明白什么是ORM了!!!

用于实现面向对象编程语言里不同类型系统数据之间的转换

username字段在数据库中为VARCHAR类型,而在Java对象中为String类型
MyBatis(12) 源码解析之SQL执行流程_第36张图片
最后回到org.apache.ibatis.executor.BaseExecutor#queryFromDatabase方法处,list中的数据也就是最后sql查询到的结果
MyBatis(12) 源码解析之SQL执行流程_第37张图片
debug结束后,最终完美拿到了我们的数据
MyBatis(12) 源码解析之SQL执行流程_第38张图片
现在再来看看这幅图,应该会更容易理解了
MyBatis(12) 源码解析之SQL执行流程_第39张图片

七、mybatis执行流程

MyBatis(12) 源码解析之SQL执行流程_第40张图片
参考:MyBatis体系结构源码解读

你可能感兴趣的:(-----,-----④,MyBatis)