【MyBatis】源码学习 04 - 从 MapperMethod 简单分析一条 SQL 的映射操作流程

news/2024/4/26 23:57:18/文章来源:https://blog.csdn.net/Michelle_Zhong/article/details/129147098

文章目录

    • 前言
    • 参考目录
    • 学习笔记
      • 1、测试代码说明
      • 2、binding 包的主要功能
      • 3、获取 Mapper 接口实例过程
      • 4、SQL 语句执行流程
      • 4.1、方法调用器
      • 4.2、`MapperMethod` 绑定方法
      • 4.2.1、`SqlCommand`
      • 4.2.2、`MethodSignature`
      • 4.3、`MapperMethod#execute`

前言

本文内容对应的是书本第 13 章的内容,主要是关于 binding 包的学习,学习了本章之后就可以知道 MyBatis 如何将 Java 接口映射成为 SQL 语句执行。

参考目录

  • 《通用源码阅读指导书:MyBatis源码详解》
    本文主要内容来自 第13章 binding包
  • 《通用源码阅读指导书——MyBatis源码详解》配套示例
    书中涉及的 Demo 示例,本文示例在 Demo1 的基础上进行了简单改造。

与上篇一样,需要说明的是,书中使用的框架版本和本文(本专栏)使用的版本不一样。

名称书中版本专栏版本
MyBatis3.5.23.5.11+
Spring Boot2.X3.X
JDK817+

随着版本的升级迭代,会有一些内容不尽相同,需要结合着进行学习。

学习笔记

由于书中讲述的内容并不是按照执行的流程来进行说明的,所以在结合 Debug 的情况下通读了两三遍之后,也大概能够理解清楚作者所说明的内容,下面将按照调用的实际顺序进行简单分析。

1、测试代码说明

代码和前面的 Demo 类似,为了测试,所以在 Mapper 中加了一个默认方法:
在这里插入图片描述

默认方法的作用下面再展开说明。

本文的流程主要是下面两行代码的执行流程:
在这里插入图片描述

下面的说明也由两部分组成:

  • 第一部分是关于 Mapper 接口实例的获取流程
  • 第二部分是关于 SQL 语句执行流程

2、binding 包的主要功能

binding包具有以下两个功能。
· 维护映射接口中抽象方法与数据库操作节点之间的关联关系;
· 为映射接口中的抽象方法接入对应的数据库操作。

3、获取 Mapper 接口实例过程

在阅读到后面之前,思考书中的说明:

每个MapperMethod对象都对应了一个数据库操作节点,调用 MapperMethod实例中的 execute方法就可以触发节点中的 SQL语句。

如果查看源码的话,这其实是一个反向推导的过程,从 MapperMethod#execute 方法开始往前回溯:

  • MapperMethod 调用具体的 SQL 语句:MapperMethod#execute
  • 前一步骤由 MapperProxy 进行调用的:MapperProxy.PlainMethodInvoker#invoke
  • MapperProxy 的实例化:MapperRegistry#getMapper

有了初步的梳理之后,下面再 Debug 进行查看。

MapperRegistry#getMapper
在这里插入图片描述

MapperProxyFactory#newInstance
在这里插入图片描述

在这里插入图片描述

4、SQL 语句执行流程

有步骤 #3 可知,Mapper 接口实例是一个代理对象,由代理对象来调用 MapperMethod#execute 方法。

将上面回溯的步骤再进行细化和简单的补充:

  • MapperProxy.PlainMethodInvoker#invoke 方法是 MapperProxy#cachedInvoker 进行调用的,该方法是获取一个方法调用器。
  • 再向上一层则是 MapperProxy#invoke,此处暂时不展开。

MapperProxy#invoke
在这里插入图片描述

4.1、方法调用器

MapperProxy#cachedInvoker
在这里插入图片描述

由于调用的是 Mapper 中的默认方法,所以会先获取默认方法的调用器,然后默认方法中由调用了 Mapper.xml 的方法,所以第二次是下面的普通方法调用器。

在这里插入图片描述

DefaultMethodInvoker是一个针对Java 8及以上版本的特性进行实现的类,用于调用接口中的默认方法。
PlainMethodInvoker是一个普通的方法调用器,用于调用Mapper接口中的普通方法。当Mapper接口中的方法不是默认方法时,就使用这个调用器执行方法调用。

两个默认方法调用器因为 JDK 版本不同所以有不同的实现方法:
在这里插入图片描述

具体的我请教了一下 ChatGPT:
在这里插入图片描述
在这里插入图片描述

4.2、MapperMethod 绑定方法

该类有两个子类 SqlCommandMethodSignature 分别对应了数据库操作和 Java 方法。

这里是引用

普通方法调用器会创建一个 MapperMethod 对象:

MapperMethod#MapperMethod
在这里插入图片描述

4.2.1、SqlCommand

在这里插入图片描述

4.2.2、MethodSignature

方法签名在之前学习参数解析的时候也有接触过。
在这里插入图片描述

MapperMethod 对象创建完成:
在这里插入图片描述

4.3、MapperMethod#execute

MapperProxy.PlainMethodInvoker#invoke
在这里插入图片描述

MapperMethod#execute
在这里插入图片描述
在这里插入图片描述

至此完成了一次数据库方法的调用。

(完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72354.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

循环、函数、对象——js基础练习

目录 一、循环练习 1.1 取款机案例 1.2 九九乘法表 1.3 根据数据生成柱形图 1.4 冒泡排序 1.6综合大练习 二、函数 2.1 转换时间案例 三、对象 1. 遍历数组对象 2. 猜数字游戏 3. 生成随机颜色 4. 学成在线页面渲染案例 一、循环练习 1.1 取款机案例 // 准备一个…

电商项目之Feign与Dubbo技术选型

文章目录1 问题背景2 前言3 思路4 Feign与Dubbo的区别5 总结6 真实案例1 问题背景 电商项目,B端以consul作为注册中心。重构了一个营销服务,以Nacos作为注册中心。B端需要调用营销服务。关于远程调用框架,营销服务用了Dubbo,而B端…

黑马程序员-Linux网络编程-01

目录 课程链接 协议 分层模型 网络传输数据封装流程 以太网帧和ARP请求 IP协议 TCP协议 BS与CS模型对比 套接字 网络字节序 IP地址转换函数 sockaddr地址结构 socket模型创建流程 socket()和bind() listen()和accept()​ 课程链接 03-协议_哔哩哔哩_bilibili 协…

java并发笔记

文章目录HashMapput方法resize方法ConcurrentHashMapput方法initTable方法sizectl代表什么:扩容计数器ConcurrentHashMap的读操作会阻塞嘛AQS唤醒线程时,AQS为什么从后往前遍历?AQS为什么要有一个虚拟的head节点AQS为什么用双向链表&#xff…

万字C语言学习笔记,带你学C带你飞(四)

文章目录单链表typedef1、基础typedef2、进阶typedef共用体枚举类型1、声明枚举类型2、定义枚举变量位域位操作文件的写入与写出C语言学习笔记,记录所学,便于复习。 由于篇幅过大,考虑到观感,准备分多篇记录。学习视频链接&#x…

Vue3.x使用Echarts绘制世界地图并进行定点

Vue3.x使用Echarts绘制世界地图并进行定点 一、需求 绘制世界地图并根据返回经纬度数据进行定点将定点数据展示在世界地图内 二、解决 绘制世界地图,利用Echarts图表组件时间,需要世界地图Geojson数据的可以在资源中下载世界地图Geojson数据-Javascr…

2022FALL嵌入式大纲

Jamslade 部分内容有遗漏,可结合 超文本 2022FALL《嵌入式系统原理》期末复习笔记 一起观看 文章目录嵌入式系统片上系统实时系统硬实时系统软实时系统伪指令DMA传输波特率单/半双/全双工通信;对齐/非对齐访问地址译码代码临界区RISCBIOSUARTSPII2CWDTRO…

2.5|shell简介|Linux支持的网络协议|Linux的网络服务

shell简介shell是一种具备特殊功能的程序,它是介于使用者和Unix/Linux操作系统内核间的一个接口。操作计算机需要通过命令(command)或是程序(program);程序需要编译器(compiler)将程…

东南大学研究生英语18-19秋试卷解析

写在前面 作者:夏日 博客地址:https://blog.csdn.net/zss192 本文为东南大学研究生英语上学期18-19年期末试卷解析,答案来源于 ChatGPT International Conference 单选题 1.A presenter is supposed to do the following in an introdu…

【数据结构趣味多】八大排序

目录 1.直接插入排序 基本思想 代码实现: 直接插入排序的特性总结: 2.希尔排序 基本思想 代码实现 (递归实现) 希尔排序的特性总结 3.直接选择排序 基本思想 代码实现: 直接选择排序的特性总结 4.堆排序 …

Springboot 全局异常处理类

全局异常处理 在开发过程中,不管是Dao、Servie、Controller,层都有可能发生异常,对于异常处理,通常是try-catch或者直接throw,这会让try-catch的代码在代码中任意出现,系统的代码耦合度高&…

深入Spring底层透析bean生命周期及循环引用的醍醐灌顶篇

目录前言一.Bean的生命周期1.1 Bean的实例化阶段1.2 Bean的初始化阶段(重点)1.3 Bean的完成阶段二.循环引用问题(面试常问题)三.Spring的三级缓存(重点来了)四.完整的Spring IoC整体总结前言 本篇是接着bean的创建基本…

2023/02/21 事件循环-eventloop 宏任务 微任务 讲解

1 JS是单线程 js是单线程的。也就是说,同一个时间只能做一件事。作为浏览器脚本语言,与它的用途有关。JavaScript的主要用途是和用户互动,以及操作DOM,这决定了它只能是单线程。 js是单线程的。也就是说,同一个时间只…

非常优秀的网站设计案例,设计师必备

厚积才能薄发,一个优秀的设计师的天性一定是想要获得更多网站设计灵感,擅于为新项目寻找创意切入点、搜索设计参考资源、最新的设计趋势。今天为大家带来了一组免费可商用的网站设计案例,通过这些网站设计案例,你可以获得&#xf…

CF707C Pythagorean Triples 题解

CF707C Pythagorean Triples 题解题目链接字面描述题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1样例 #2样例输入 #2样例输出 #2样例 #3样例输入 #3样例输出 #3样例 #4样例输入 #4样例输出 #4样例 #5样例输入 #5样例输出 #5提示思路代码实现题目 链接 http…

华为OD机试 - 最短耗时(C++) | 附带编码思路 【2023】

刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…

算法笔记(十一)—— 并查集、KMP

并查集 支持集合快速合并 所有数据生成各自的集合,需要提供查询两个两素是不是属于一个集合,和集合合并操作,并查集能够在常数时间级别上对两个操作进行实现 1. 构造结构(数据指针),将自己的指针指向自己…

事件流、事件冒泡、阻止冒泡

1、事件流 2、事件冒泡&#xff1a;从小到大 概念&#xff1a; 当一个元素的事件被触发时&#xff0c;同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡 <style> .father{width: 300px;height: 300px;background-color: pink; } .son{width:…

Zookeeper框架

Zookeeper框架概述 1.Zookeeper介绍 Zookeeper&#xff08;以下简称ZK&#xff09;是用来管理和协调其他框架的&#xff0c;很多框架需要依赖ZK&#xff08;例如Hadoop-HA&#xff0c;Kafka&#xff0c;HBase等&#xff09;ZK本身也是一个集群ZK本身也可以存数据(一般保存配置…

koa中间件的实现原理

koa中间件的实现原理如何&#xff1f;先来看一个例子。koa的执行顺序是这样的&#xff1a;const middleware asyncfunction (ctx, next) {console.log(1)await next()console.log(6) }const middleware2 asyncfunction (ctx, next) {console.log(2)await next()console.log(5…