我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java MyBatis是如何执行一条SQL语句的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java MyBatis是如何执行一条SQL语句的

背景

在前两天的一次面试中,面试官问了一个和标题一样的问题,由于一直认为MyBatis只是一个ORM框架,所以并没有对他有过深入的了解,于是被问到了,那么这一篇文章来从源码探究一下MyBatis是如何执行一条SQL语句的。

阅读环境

源码环境,github直接下载的main分支代码,版本号为 3.5.11-SNAPSHOT

Ide Jetbrain Idea 2021.2.1 社区版
Maven 3.8.2
JDK 17

配置文件:

<?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>
  <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:/**"/>
        <property name="username" value="****"/>
        <property name="password" value="******"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="LogChartMapper.xml"/>
  </mappers>
</configuration>

测试主方法:

public class Main {
  public static void main(String[] args) throws IOException {
    InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
    SqlSession sqlSession = build.openSession();
    LogChartMapper mapper = sqlSession.getMapper(LogChartMapper.class);
    List<LogChart> logCharts = mapper.selectList();
    System.out.println(JSONUtil.toJsonStr(logCharts));
  }
}

mapper

public interface LogChartMapper {
  @Select(value = "select * from log_chart")
  List<LogChart> selectList();
}

mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.mybatis.test.mapper.LogChartMapper">
</mapper>

阅读过程

加载XML的过程

从上方的测试主方法可以看到,比较重要的是 SqlSessionFactory,第一步需要看的就是他是被如何构建出来的,点击build方法,跟进去。

Build方法追到最下面,构建了一个XMLConfigBuilder,那么这个Parser方法,有必要进去看一下。

这段代码比较简短,可以看到两个信息点。第一个返回的类型是Configuration类,调用了一个parseConfiguration方法,并且传入的configuration的xml节点。
说明方法进入是对的,后续我们继续跟一下 parseConfiguration方法

针对这个方法,看到几个眼熟的东西。分别是解析 plugins、objectFactory、mappers 这些标签的。其他的我们这里不关心,我们主要看一下处理 Mappers 标签的这个方法。

这里通过遍历我们写的每个mapper标签,会得到resource、url、mapperClass这三个变量。他们在配置时是互斥的。 这里的三个if,也对应了每个不为空的情况。

我们的XML使用的是Resources属性,可以回到上面翻XML,我们这里看Resource标签不为空的 if 判断即可。

这里注意看,Myabtis去读取了Mapper指向的xml,然后new了一个XmlMapperBuilder,随后调用了parse方法,这里的逻辑和刚刚开头的地方很相似。值得注意的是在创建XmlMapperBuilder的时候吧Configuration传了进去,也就是说在parse中是会改变这个configuration里面的东西的。到这里接着往里面跟代码。

看名字有两个比较重要的方法,ConfigurationElement、binMapperForNameScpace。
configurationElement 看这个方法的入参,大概率是对XML做一些处理,像ResultMap、sql、select这些标签做处理,我这里没有用到就不说了,感兴趣的可以自己阅读一下。

后面主要看一下BindMapperForNameSpace方法。

创建Mapper

上面的代码中,看到了AddMapper这个方法,传入的值,是刚刚xml中配置的nameSpace,也就是Mapper类的完整类名,追进去看一下。

看到这里,知道了一个知识点,为什么Mapper类一定要是 Interface,如果不是interface,这个方法就进不来了。

注意看了,有一个细节,向knownMappers中,以这个class为键,放入了一个MapperProxyFactory。到达这里,就可以得知。所有的Mapper方法,都是由代理类去调用的。

接下来往下,又看到一个相似的,parse方法,看他的类名 MapperAnnotationBuilder 是用来处理注解的,往里追看一下。

这里的圈出来的 IF 判断,判断方法上有Select 或者 SelectProvider注解,并且没有ResultMap注解的。会去解析ResultMap,这里大概率是根据返回值,去遍历属性这里就跳过了,进入下一个方法。

parseStatement方法像是去解析方法了,代码有点多,这里就不粘贴了,感兴趣可以自己看一下,知道这里是去解析方法就可以了。

到这里结束,最后返回了SqlSessionFactory类。

获得一个Mapper

SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = build.openSession();
LogChartMapper mapper = sqlSession.getMapper(LogChartMapper.class);

knownMapper 这个对象很眼熟是不是,这个在上面有提到过,以Class为Key,value时MapperProxyFactory,所以这里可以Get出来一个工厂,然后点用了newInstance方法,追进去看一下。

这里看到是Java原生的动态代理,这里返回的是一个代理对象。

执行一个Mapper的方法

因为看到这里时Java的动态代理,所以也很显而易见的得知。MapperProxy实现了InvocationHandler接口。

实现这个接口,会重写Invoke方法。也就是说,我们虽然代码上写的是调用的我们Mapper中指向的方法,但是其实jvm会去调用这个invoke方法,接下来直接去追Invoke方法。

由于我们mapper是接口,所以上面的if是为false的,也就是else是我们执行的代码,接着往里追。

这里可以看到new了一个PlainMethodInvoker,然后调用他的invoke方法,追进来。

接下来这个Execute就是他的具体执行Select语句的地方了。

由于后面的代码有点长,我这里就摘取了一小段关键的地方。看一下即可。

结论

MyBatis先读取配置文件生成一个configuration对象,然后会生成对应的XmlParseBuilder,在对应的XmlParseBuilder会向configuration中的knowMapper中,放入对应的MapperProxyFactory。然后要执行mapper方法的时候,会通过mapperProxyFactory拿到一个Mapper的动态代理对象。随后会动态代理对象会根据当前的方法去判断调用SqlSession的不同的方法来执行Sql语句。

到此这篇关于Java MyBatis是如何执行一条SQL语句的的文章就介绍到这了,更多相关MyBatis执行SQL语句内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java MyBatis是如何执行一条SQL语句的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java MyBatis是怎么执行一条SQL语句的

今天小编给大家分享一下Java MyBatis是怎么执行一条SQL语句的的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。阅读环
2023-07-02

一条SQL更新语句是如何执行的

文章首发于公众号「蝉沐风」,认真写好每一篇文章,欢迎大家关注交流这是图解MySQL的第2篇文章,这篇文章会通过一条SQL更新语句的执行流程让大家清楚地明白:什么是InnoDB页?缓存页又是什么?为什么这么设计?什么是表空间?不同存储引擎的表在文件系统的底层表示
一条SQL更新语句是如何执行的
2014-08-03

一条SQL查询语句是如何执行的?

导读Mysql在中小型企业中是个香饽饽,目前主流的数据库之一,几乎没有一个后端开发者不会使用的,但是作为一个老司机,仅仅会用真的不够。今天陈某透过一个简单的查询语句来讲述在Mysql内部的执行过程。select * from table where id=10
一条SQL查询语句是如何执行的?
2019-06-13

分析mysql中一条SQL查询语句是如何执行的

目录一、MySQL 逻辑架构概览二、连接器(Connector)三、查询缓存(Query Cache)四、解析器(Parser)五、优化器(Optimizer)六、执行器七、小结一、MySQL 逻辑架构概览 MySQL 最重要、最与众不同的
2022-05-30

MyBatis中SQL语句是怎么执行的

MyBatis中的SQL语句执行流程大致如下:配置文件:首先在配置文件(通常是mybatis-config.xml)中配置数据库连接信息、映射文件等。映射文件:在映射文件(通常是mapper.xml)中编写SQL语句、参数映射、结果映射等。
MyBatis中SQL语句是怎么执行的
2024-04-23

02 | 日志系统:一条SQL更新语句是如何执行的?

极客时间专栏《MySQL实战45讲》的阅读笔记。
02 | 日志系统:一条SQL更新语句是如何执行的?
2015-04-30

02.日志系统:一条SQL更新语句是如何执行的?

我们还是从一个表的一条更新语句说起,我们创建下面一张表: create table T(ID int primary key, c int);    如果要将ID=2这一行c的值加1,SQL可以这么写: update T set c=c+1 where ID=
02.日志系统:一条SQL更新语句是如何执行的?
2015-02-19

MyBatis的SQL语句执行过程是什么

这篇文章主要介绍“MyBatis的SQL语句执行过程是什么”,在日常操作中,相信很多人在MyBatis的SQL语句执行过程是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MyBatis的SQL语句执行过程
2023-06-30

一条SQL更新语句的执行过程是什么

这篇“一条SQL更新语句的执行过程是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“一条SQL更新语句的执行过程是什么”文
2023-06-30

MyBatis ORM的SQL语句执行流程

MyBatis ORM(Object-Relational Mapping,对象关系映射)是一个用于Java编程语言的持久层框架,它允许你将数据库表映射到Java对象,从而简化了数据库操作。MyBatis ORM的SQL语句执行流程如下:配
MyBatis ORM的SQL语句执行流程
2024-09-16

MyBatis ORM的SQL语句执行跟踪

MyBatis ORM(Object-Relational Mapping,对象关系映射)是一个用于简化数据库操作的持久层框架。在使用MyBatis ORM时,可以通过日志记录和调试来跟踪SQL语句的执行情况。以下是一些建议:配置日志记录器
MyBatis ORM的SQL语句执行跟踪
2024-09-15

MyBatis ORM的SQL语句执行统计

MyBatis ORM 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。要统计 MyBatis ORM 中的 SQL 语句执行情况,可以使用 MyBatis 提供的插件功能。以下是一个简单的示例,展示如何使用 MyBa
MyBatis ORM的SQL语句执行统计
2024-09-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录