一次Mybaits查询的源码分析
很好奇Mybaits是怎么将xml和mapper对应起来的,用一段比较简单的demo去debug追踪一下源码看看
先用xml配置的方式,看懂了再去看注解的方式是怎么实现的
获取Mapper
Mybaits是如何从xml中加载到mapper的
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.github.yeecode.mybatisdemo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/github/yeecode/mybatisdemo/UserMapper.xml"/>
</mappers>
</configuration>
在xml中有mapper标签,应该是从这里加载到配置
示例代码
public static void main(String[] args) {
// 第一阶段:MyBatis的初始化阶段
String resource = "mybatis-config.xml";
// 得到配置文件的输入流
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
// 得到SqlSessionFactory
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
// 第二阶段:数据读写阶段
try (SqlSession session = sqlSessionFactory.openSession()) {
// 找到接口对应的实现
UserMapper userMapper = session.getMapper(UserMapper.class);
// 组建查询参数
User userParam = new User();
userParam.setSchoolName("Sunny School");
// 调用接口展开数据库操作
List<User> userList = userMapper.queryUserBySchoolName(userParam);
// 打印查询结果
for (User user : userList) {
System.out.println("name : " + user.getName() + " ; email : " + user.getEmail());
}
}
}
从UserMapper userMapper = session.getMapper(UserMapper.class);此处开始debug,看看是怎么获取到mapper的

一路点进来发现是从一个Map中去获取mapper对象
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
那么是从什么时候填充knownMappers的呢

这个对象的方法不只有获取mapper,还有添加mapper,找一个添加方法继续断底点

找到是找到了,但是不知道什么时候调用的,可以通过IDEA的调用栈


最后发现了,是加载xml的时候,去解析mapper标签里的值,然后再通过类加载器去加载资源,最后加载到knownMappers中,还有去解析xml中的sql的过程
这样子xml就和mapper就对应起来了,虽然知道了mapper和xml的对应关系,但是不知道怎么通过调用mapper里的方法,去找到对应的sql
在对 List<User> userList = userMapper.queryUserBySchoolName(userParam);debug时,没有进入到mapper方法中,而是会进入到一个代理类中


刚刚在getMapper()中给UserMapper创建了代理,那么大概知道是mapper和xml是怎么关联的了,当调用mapper时,会被MapperProxy代理,去执行查询方法时,通过上边的knownMappers
获取到mapper对应的xml,这样代理类就知道要调用的方法和对应的sql的哪里

最终时通过mapperMethod.execute(sqlSession, args);去执行查询的,点进去一看发现对各种sql类型做了处理

select的查询原来通过返回值来选择不同的处理

很好奇这些属性是怎么判断的,找到对应的类继续断点

原来是在execute之前去赋值,而且这个方法会把调用方法对应的xml中的方法找到

通过获取到方法的返回值,然后再去做对比,我这个方法返回的是list,就命中了returnMany,在继续断点,找到了真正执行的方法

这里就已经将关联的xml信息带过来了


继续看会看到缓存相关的代码,如果命中了缓存就直接返回了,我这里没有就继续开了一个线程往下执行,delegate是一个Executor

最后的查询到了这里,就是调用mysql的包了,在statement中,已经把sql、参数和连接配置什么的都封装好了
查询完后把结果返回到statement,但是返回的内容很多,查询结果记录在这里

查询总结:
- 在进行数据库查询前,先查询缓存;没有名中,则数据库查询之后的结果也放入缓存中
- SQL 语句的执行经过了层层转化,依次经过了 MappedStatement 对象、Statement对象和 PreparedStatement对象,最后才交给mysql执行
- 最终数据库查询得到的结果交给 ResultHandler对象处理
返回结果
将结果映射到实体类上这段代码有点绕,调用链很长

首先是这里先创建输出的实体类,就是resultMap里定义的对象

创建好实体后,把实体传输给下一个方法,填充实体

将实体字段和结果集里的字段对应起来,然后根据字段去获取对应的值,然后把值设置到实体里,通过循环遍历全部字段

这样走一圈回来,一个对象就映射好了,再经过循环,就把全部的对象都拿到了,最后再将这些对象封装到multipleResults集合里,这个集合就是返回值了

映射总结:
- 获取并创建实体类
- 将实体类的字段和结果集的字段一一对应,然后再填充实体的值
- 最后返回实体集合
总结
以上就是Mybaits读取xml,然后查询的过程了,整个过程还是很复杂的,很多层封装和跳转,但是大大的提高了我们开发的效率
然后再把总结发一下
获取配置总结:
- 得到配置文件然后转换成输入流
- 将输入流传给
SqlSessionFactoryBuilder创建SqlSessionFactory - 扫描xml文件并加载,然后将xml和mapper的对应关系填充好
查询总结:
- 在进行数据库查询前,先查询缓存;没有名中,则数据库查询之后的结果也放入缓存中
- SQL 语句的执行经过了层层转化,依次经过了 MappedStatement 对象、Statement对象和 PreparedStatement对象,最后才交给mysql执行
- 最终数据库查询得到的结果交给 ResultHandler对象处理
映射总结:
- 获取并创建实体类
- 将实体类的字段和结果集的字段一一对应,然后再填充实体的值
- 最后返回实体集合
一次Mybaits查询的源码分析的更多相关文章
- MyBatis原理分析之四:一次SQL查询的源码分析
上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的. 准备工作 Mybatis完成一次SQL查询需要使用的代码如下: ) { ); ) { throw ne ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- mybaits源码分析(一)
一.源码下载 1.手动编译源码 为了方便在看源码的过程中能够方便的添加注释,可以从官网下载源码编译生成对应的Jar包,然后上传到本地maven仓库,再引用这个Jar. 首先需要编译打包parent项目 ...
- Solr4.8.0源码分析(6)之非排序查询
Solr4.8.0源码分析(6)之非排序查询 上篇文章简单介绍了Solr的查询流程,本文开始将详细介绍下查询的细节.查询主要分为排序查询和非排序查询,由于两者走的是两个分支,所以本文先介绍下非排序的查 ...
- Solr4.8.0源码分析(5)之查询流程分析总述
Solr4.8.0源码分析(5)之查询流程分析总述 前面已经写到,solr查询是通过http发送命令,solr servlet接受并进行处理.所以solr的查询流程从SolrDispatchsFilt ...
- Mybatis源码分析--关联表查询及延迟加载原理(二)
在上一篇博客Mybatis源码分析--关联表查询及延迟加载(一)中我们简单介绍了Mybatis的延迟加载的编程,接下来我们通过分析源码来分析一下Mybatis延迟加载的实现原理. 其实简单来说Myba ...
随机推荐
- golang pprof 监控系列(3) —— memory,block,mutex 统计原理
golang pprof 监控系列(3) -- memory,block,mutex 统计原理 大家好,我是蓝胖子. 在上一篇文章 golang pprof监控系列(2) -- memory,bloc ...
- 快速上手Linux核心命令(三):文件和目录操作命令
@ 目录 前言 cd 切换目录 pwd 显示当前路径 ls 显示目录下内容及相关属性信息 mkdir 创建目录 tree 以树形结构显示目录下的内容 touch 创建空白文件或改变文件的时间戳属性 c ...
- 分布式文件存储MinIO、安装和使用
1.MinIO简介 MinIO是高性能的对象存储,单个对象最大可达5TB.适合存储图片.视频.文档.备份数据.安装包等一系列文件.是一款主要采用Golang语言实现发开的高性能.分布式的对象存储系统. ...
- Python 列表的修改、添加和删除元素
列表修改.添加和删除元素 大多数创建的列表都是动态的,随程序的运行增删元素 修改列表元素 指定列表名和要修改的元素的索引,再指定要修改元素的新值 # 修改列表元素案例 motorcycles = [' ...
- 从源码深入理解读写锁(golang-RWMutex)
环境:go 1.19.8 在读多写少的情况下,即使一段时间内没有写操作,大量并发的读访问也不得不在Mutex的保护下变成串行访问,这种情况下,使用Mutex,对性能影响比较大. 所以就要区分读写操作. ...
- 云原生时代崛起的编程语言Go常用标准库实战
@ 目录 基础标准库 简述 字符串-string 底层结构 函数 长度 格式化输出 模版-template text/template html/template 正则表达式-regexp 编码-en ...
- ReactHub:我用 ChatGPT 搞了一个 React 的资源导航网站,谁有我用心啊!
大家好,我是DOM哥. 图谱年年有,今年我来盘! 之前已经盘完了 Vue 的技术图谱,今天来盘 React 的. 我用 ChatGPT 开发了一个 React 的资源导航网站. 不管你是资深 Reac ...
- 一文快速入门体验 Hibernate
前言 Hibernate 是一个优秀的持久层的框架,当然,虽然现在说用得比较多的是 MyBaits,但是我工作中也不得不接触 Hibernate,特别是一些老项目需要你维护的时候.所以,在此写下这篇文 ...
- Python网页开发神器fac 0.2.8、fuc 0.1.28新版本更新内容介绍
fac项目地址:https://github.com/CNFeffery/feffery-antd-components fuc项目地址:https://github.com/CNFeffery/fe ...
- jenkins的安装和配置(flask结合jenkins半自动化部署流程)
jenkins在虚拟机中安装 1.1 背景介绍 Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建.测试和部署等功能. Je ...