MyBatis 源码解析:Mapper 文件加载与解析
引言
在 MyBatis 中,Mapper 文件扮演了至关重要的角色,它通过 SQL 映射文件来定义数据库查询操作和 Java 对象之间的映射关系。Mapper 文件通常是以 XML 格式存储的,包含了 SQL 语句以及与 Java 对象的对应关系。在本篇文章中,我们将通过自定义实现一个简单的 Mapper 文件解析器,展示 MyBatis 是如何加载和解析这些 SQL 映射文件的,并对其内部的工作原理进行详细剖析。
摘要
Mapper 文件是 MyBatis 中连接 SQL 和 Java 对象的桥梁。本文将通过自定义实现一个简单的 Mapper 文件加载与解析器,展示其工作原理,并对比 MyBatis 中的 Mapper 文件解析过程,帮助读者理解 MyBatis 内部的 Mapper 文件加载与解析机制。
什么是 MyBatis Mapper 文件
在 MyBatis 中,Mapper 文件是用来定义 SQL 语句和 Java 对象之间映射关系的文件。通常,一个 Mapper 文件以 XML 的格式存在,并且定义了诸如<select>、<insert>、<update>、<delete>等标签,用来映射 SQL 语句。
一个典型的 Mapper 文件示例如下:
<mapper namespace="com.example.mapper.UserMapper"><select id="getUserById" parameterType="int" resultType="User">SELECT * FROM users WHERE id = #{id}</select><insert id="insertUser" parameterType="User">INSERT INTO users (name, age) VALUES (#{name}, #{age})</insert>
</mapper>
在上面的示例中,<mapper> 标签定义了一个命名空间,<select> 和 <insert> 标签分别定义了 SQL 查询和插入语句。
手动实现 Mapper 文件加载与解析
接下来,我们将通过一个简化的自定义实现,展示如何加载和解析 MyBatis 的 Mapper 文件。
步骤概述
- 定义 Mapper 解析器:创建一个简单的 Mapper 文件加载和解析器。
- 加载 XML 文件:读取并解析 XML 文件中的 SQL 映射。
- 解析 SQL 映射:解析
<select>和<insert>标签中的 SQL 信息。 - 实现测试类:验证自定义 Mapper 文件解析器的工作流程。
定义 Mapper 解析器
首先,我们定义一个简单的 MapperFileParser 类,用于加载和解析 XML 格式的 Mapper 文件。
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;/*** Mapper 文件解析器,用于加载和解析 XML 格式的 SQL 映射文件*/
public class MapperFileParser {/*** 解析给定的 Mapper 文件* @param filePath Mapper 文件路径*/public void parseMapperFile(String filePath) {try {// 加载并解析 XML 文件File file = new File(filePath);DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(file);// 获取根元素 <mapper>Element rootElement = document.getDocumentElement();String namespace = rootElement.getAttribute("namespace");System.out.println("Mapper namespace: " + namespace);// 解析 <select> 和 <insert> 等标签NodeList nodeList = rootElement.getChildNodes();for (int i = 0; i < nodeList.getLength(); i++) {Node node = nodeList.item(i);// 处理 <select> 标签if (node instanceof Element && "select".equals(node.getNodeName())) {Element selectElement = (Element) node;String id = selectElement.getAttribute("id");String parameterType = selectElement.getAttribute("parameterType");String resultType = selectElement.getAttribute("resultType");String sql = selectElement.getTextContent().trim();System.out.println("Select ID: " + id + ", Parameter Type: " + parameterType + ", Result Type: " + resultType);System.out.println("SQL: " + sql);}// 处理 <insert> 标签if (node instanceof Element && "insert".equals(node.getNodeName())) {Element insertElement = (Element) node;String id = insertElement.getAttribute("id");String parameterType = insertElement.getAttribute("parameterType");String sql = insertElement.getTextContent().trim();System.out.println("Insert ID: " + id + ", Parameter Type: " + parameterType);System.out.println("SQL: " + sql);}}} catch (Exception e) {e.printStackTrace();}}
}
说明:
- 我们使用了 Java 的
DocumentBuilderFactory和DocumentBuilder来解析 XML 文件,并获取 Mapper 文件中的 SQL 语句。 parseMapperFile()方法负责加载 XML 文件并解析其中的<select>和<insert>标签。
加载 XML 文件
接下来,我们通过 MapperFileParser 类加载并解析 Mapper 文件。
public class MapperFileParserTest {public static void main(String[] args) {// 创建解析器MapperFileParser parser = new MapperFileParser();// 解析示例 Mapper 文件String filePath = "src/main/resources/UserMapper.xml"; // 指定 Mapper 文件路径parser.parseMapperFile(filePath);}
}
示例 Mapper 文件(UserMapper.xml):
<mapper namespace="com.example.mapper.UserMapper"><select id="getUserById" parameterType="int" resultType="User">SELECT * FROM users WHERE id = #{id}</select><insert id="insertUser" parameterType="User">INSERT INTO users (name, age) VALUES (#{name}, #{age})</insert>
</mapper>
测试结果
运行解析器后,输出结果如下:
Mapper namespace: com.example.mapper.UserMapper
Select ID: getUserById, Parameter Type: int, Result Type: User
SQL: SELECT * FROM users WHERE id = #{id}
Insert ID: insertUser, Parameter Type: User
SQL: INSERT INTO users (name, age) VALUES (#{name}, #{age})
我们成功解析了 Mapper 文件中的命名空间、SQL 语句、以及其参数类型和结果类型。
类图与流程图
为了更好地理解 Mapper 文件的加载与解析过程,我们提供了类图和流程图。
类图
流程图
MyBatis中的 Mapper 文件加载与解析
在 MyBatis 中,Mapper 文件的加载和解析是通过 XMLMapperBuilder 类来完成的。XMLMapperBuilder 负责读取 Mapper 文件并将其映射为 MyBatis 的内存结构。MyBatis 使用 XPath 解析 XML 文件,处理 SQL 映射、参数类型和结果类型。
MyBatis的 XML 解析
MyBatis 使用了 XPathParser 类来解析 Mapper 文件的内容:
public class XMLMapperBuilder extends BaseBuilder {private final XPathParser parser;private final MapperBuilderAssistant builderAssistant;public XMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource, Map<String, XNode> sqlFragments) {super(configuration);this.parser = new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver());this.builderAssistant = new MapperBuilderAssistant(configuration, resource);}public void parse() {parseMapper(parser.evalNode("/mapper"));}
}
MyBatis中的 Mapper 文件结构
在 MyBatis 中,Mapper 文件的结构通常包括:
- 命名空间:标识 Mapper 文件的唯一性。
- SQL 语句:通过
<select>、<insert>、<update>和<delete>标签定义 SQL 语句。 - 参数和结果映射:指定 SQL 语句的参数类型和结果类型。
MyBatis 在解析这些 Mapper 文件时,会将 SQL 语句映射到 Java 方法上,结合动态 SQL 生成最终的 SQL 语句。
对比分析:手动实现与 MyBatis 的区别
1
. 功能复杂度:
- MyBatis:MyBatis 的 Mapper 文件解析器支持复杂的动态 SQL、嵌套查询、缓存等功能,并且能够自动管理 SQL 的参数和结果映射。
- 简化实现:我们的手动实现仅支持解析简单的 SQL 映射,没有处理动态 SQL、结果集映射和缓存等复杂特性。
-
扩展性:
- MyBatis:MyBatis 支持丰富的扩展机制,如自定义插件、拦截器等,能够灵活应对不同的业务需求。
- 简化实现:我们的实现是一个基础的解析器,主要用于展示 XML 文件解析的基本原理,缺乏高级扩展能力。
-
性能和优化:
- MyBatis:MyBatis 针对大规模应用进行了大量的性能优化,能够高效地解析和管理大量的 Mapper 文件。
- 简化实现:我们实现的版本没有进行性能优化,适用于简单的场景。
总结
通过手动实现一个简化的 Mapper 文件解析器,我们了解了 MyBatis 是如何加载和解析 XML 格式的 SQL 映射文件的。MyBatis 的 Mapper 文件解析机制非常灵活,能够将 SQL 语句与 Java 对象进行紧密的绑定,使得开发者能够以更加简洁的方式处理数据库操作。理解 Mapper 文件的加载与解析原理,将帮助您在实际项目中更好地使用 MyBatis 并优化 SQL 操作。
互动与思考
你在项目中是否遇到过需要解析 SQL 配置文件的场景?你认为 MyBatis 的 Mapper 文件机制在哪些方面最有帮助?欢迎在评论区分享你的经验与见解!
如果你觉得这篇文章对你有帮助,请别忘了:
- 点赞 ⭐
- 收藏 📁
- 关注 👀
让我们一起深入学习 MyBatis 框架,成为更优秀的开发者!
相关文章:
MyBatis 源码解析:Mapper 文件加载与解析
引言 在 MyBatis 中,Mapper 文件扮演了至关重要的角色,它通过 SQL 映射文件来定义数据库查询操作和 Java 对象之间的映射关系。Mapper 文件通常是以 XML 格式存储的,包含了 SQL 语句以及与 Java 对象的对应关系。在本篇文章中,我…...
(11)(2.1.2) DShot ESCs(二)
文章目录 前言 3 配置伺服功能 4 检查RC横幅 5 参数说明 前言 DShot 是一种数字 ESC 协议,它允许快速、高分辨率的数字通信,可以改善飞行器控制,这在多旋翼和 quadplane 应用中特别有用。 3 配置伺服功能 如上所述,如果使用…...
yolov5/8/9模型在COCO分割数据集上的应用【代码+数据集+python环境+GUI系统】
yolov5/8/9模型在COCO分割数据集上的应用【代码数据集python环境GUI系统】 yolov5/8/9模型在COCO分割数据集上的应用【代码数据集python环境GUI系统】 1.COCO数据集介绍 COCO数据集,全称为Microsoft Common Objects in Context,是微软于2014年出资标注的…...
技术周总结 09.16~09.22 周日(架构 C# 数据库)
文章目录 一、09.16 周一1.1)问题01: 软件质量属性中"质量属性场景"、"质量属性环境分析"、"质量属性效用树"、"质量属性需求用例分析"分别是什么?1.2)问题02: 软件质量属性中…...
【java实现json转化为CSV文件】
文章目录 JSON文件中的数据格式测试文件转换的接口 JSON文件中的数据格式 单条数据展开后如下: {"text": "《邪少兵王》是冰火未央写的网络小说连载于旗峰天下","spo_list":[{"predicate": "作者", "objec…...
MySQL索引知识个人笔记总结(持续整理)
本篇笔记是个人整理的索引知识总结,刚开始有点乱,后续会一直边学边整理边总结 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。就好比索引就是数据的目录 索引结构 Btree索引,Hash索引,Full-text索引,R-tree(空…...
ReKep——李飞飞团队提出的让机器人具备空间智能:基于视觉语言模型GPT-4o和关系关键点约束
前言 由于工厂、车厂的任务需求场景非常明确,加之自今年年初以来,我司在机器人这个方向的持续大力度投入(包括南京、长沙两地机器人开发团队的先后组建),使得近期我司七月接到了不少来自车厂/工厂的订单,比如其中的三个例子&…...
[Java并发编程] synchronized(含与ReentrantLock的区别)
文章目录 1. synchronized与ReentrantLock的区别2. synchronized的作用3. synchronized的使用3.1 修饰实例方法,作用于当前实例,进入同步代码前需要先获取实例的锁3.2 修饰静态方法,作用于类的Class对象,进入修饰的静态方法前需要…...
spring-boot-maven-plugin插件打包和java -jar命令执行原理
文章目录 1. Maven生命周期2. jar包结构2.1 不可执jar包结构2.2 可执行jar包结构 3. spring-boot-maven-plugin插件打包4. 执行jar原理 1. Maven生命周期 Maven的生命周期有三种: clean:清除项目构建数据,较为简单,不深入探讨&a…...
Python办公自动化教程(001):PDF内容提取
1、Pdfplumber介绍 pdfplumber的github地址: https://github.com/jsvine/pdfplumber/【介绍】:pdfplumber 是一个用于处理 PDF 文件的 Python 第三方库,它提供了一种方便的方式来提取 PDF 文件中的文本、表格和其他信息。【功能】ÿ…...
HarmonyOS鸿蒙开发实战(5.0)自定义全局弹窗实践
鸿蒙HarmonyOS开发实战往期文章必看: HarmonyOS NEXT应用开发性能实践总结 最新版!“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通) 非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&am…...
【AI学习】了解OpenAI o1背后的self-play RL:开启新的智能道路
在ChatGPT刚刚出来的时候,沐神关于ChatGPT有一段视频,只有几分钟,却是讲得极其透彻的一段。大概意思就是,过去的AI智能水平,比如五年前,大概相当于人类5秒钟思考的程度,包括自动驾驶,…...
Java项目实战II基于Java+Spring Boot+MySQL的车辆管理系统(开发文档+源码+数据库)
目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 "随着…...
IPsec-VPN中文解释
网络括谱图 IPSec-VPN 配置思路 1 配置IP地址 FWA:IP地址的配置 [FW1000-A]interface GigabitEthernet 1/0/0 [FW1000-A-GigabitEthernet1/0/0]ip address 10.1.1.1 24 //配置IP地址 [FW1000-A]interface GigabitEthernet 1/0/2 [FW1000-A-GigabitEthernet1/0/2]ip a…...
Ubuntu 22.04 源码下载、编译
Kernel/BuildYourOwnKernel - Ubuntu Wikihttps://wiki.ubuntu.com/Kernel/BuildYourOwnKernel 一、查询当前系统内核版本 rootubuntu22:~# uname -r 5.15.0-118-generic 二、查询本地软件包数据库中的内核源码信息 rootubuntu22:~# apt search linux-source Sorting... Do…...
【深度学习实战—11】:基于Pytorch实现谷歌QuickDraw数据集的下载、解析、格式转换、DDP分布式训练、测试
✨博客主页:王乐予🎈 ✨年轻人要:Living for the moment(活在当下)!💪 🏆推荐专栏:【图像处理】【千锤百炼Python】【深度学习】【排序算法】 目录 😺〇、仓库…...
基于SpringBoot+WebSocket实现地图上绘制车辆实时运动轨迹图
实现基于北斗卫星的车辆定位和轨迹图的Maven工程(使用模拟数据),我们将使用以下技术: Spring Boot:作为后端框架,用来提供数据接口。Thymeleaf:作为前端模板引擎,呈现网页。Leaflet…...
嵌入式入门小工程
此代码基于s3c2440 1.点灯 //led.c void init_led(void) {unsigned int t;t GPBCON;t & ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));t | (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);GPBCON t; }void le…...
hackmyvm靶场--zon
环境 攻击机kali 靶机 未知 主机探测 因为在同一个局域网内使用ARP协议探测存活主机 靶机为192.168.56.128 端口探测 常见的80和22端口 那么一定是寻找web漏洞拿shell了 后台扫描 后台扫描常用dirsearch和gobuster,有时候小字典可能不太行,可以尝试换个大点…...
atcoder abc372 启发式合并, dp
A delete 代码: #include <bits.stdc.h>using namespace std;int main() {string s;cin >> s;for(auto t: s) if(t ! .) cout << t; } B 3 ^ A 思路:三进制转换,可以参考二进制,先把当前可以加入的最大的3的…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
