Mybatis的SqlSource SqlNode BoundSql

学习链接

MyBatis SqlSource解析

【Mybatis】Mybatis源码之SqlSource#getBoundSql获取预编译SQL

Mybatis中SqlSource解析流程详解

Mybatis TypeHandler解析

图解

Mybatis的SqlSource&SqlNode - processon

在这里插入图片描述

DynamicSqlSource

public class DynamicSqlSource implements SqlSource {private final Configuration configuration;private final SqlNode rootSqlNode;public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {this.configuration = configuration;this.rootSqlNode = rootSqlNode;}/*** 获取一个BoundSql对象** DynamicSqlSource和 RawSqlSource都会转化为 StaticSqlSource,然后才能给出一个 BoundSql对象。** @param parameterObject 参数对象* @return BoundSql对象*/@Overridepublic BoundSql getBoundSql(Object parameterObject) {// 创建DynamicSqlSource的辅助类,用来记录DynamicSqlSource解析出来的SQL片段信息和参数信息DynamicContext context = new DynamicContext(configuration, parameterObject);// 这里会从根节点开始,对节点逐层调用apply方法,经过这一步后,动态节点"${}"都被替换,这样 DynamicSqlSource便不再是动态的,而是静态的。rootSqlNode.apply(context);// 处理占位符,汇总参数信息SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);	    Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();// 使用SqlSourceBuilder处理"#{}",将其转化为"?",然后创建ParameterMapping,最终生成了StaticSqlSource对象SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());BoundSql boundSql = sqlSource.getBoundSql(parameterObject);// 把context.getBindings()的参数放到boundSql的metaParameters中进行保存context.getBindings().forEach(boundSql::setAdditionalParameter);return boundSql;}}	

RawSqlSource

通过观察RawSqlSource与DynamicSqlSource的区别,可以注意到:

  1. 首先需要判定在mapper.xml中写的一个sql标签语句到底是动态sqlSource还是rawSqlSource?这个在XMLScriptBuilder#parseDynamicTags中有解析过程,凡是含有${} 或者 还有动态标签(如trim,where,if等9个标签)的 的都是动态的
  2. DynamicSqlSource和RawSqlSource有什么共同点和区别?它们都有解析阶段 和 运行阶段,在解析阶段时,RawSqlSource在构造方法中就已经得到了StaticSqlSource了(因为里面没有需要动态解析的内容了,注意#{}不属于动态解析的范畴,只有那9个动态标签和${}才算动态的),而DynamicSqlSource需要在运行阶段根据传参,才能获得StaticSqlSource,需要根据实际传参才能确定sql,所以叫动态嘛。所以它们最终都会获取StaticSqlSource,参与后面的流程。
public class RawSqlSource implements SqlSource {private final SqlSource sqlSource;public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {this(configuration, getSql(configuration, rootSqlNode), parameterType);}public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);Class<?> clazz = parameterType == null ? Object.class : parameterType;sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());}private static String getSql(Configuration configuration, SqlNode rootSqlNode) {DynamicContext context = new DynamicContext(configuration, null);rootSqlNode.apply(context);return context.getSql();}@Overridepublic BoundSql getBoundSql(Object parameterObject) {return sqlSource.getBoundSql(parameterObject);}}

GenericTokenParser#parse

/*** 该方法主要 完成占位符的定位工作,然后把占位符的替换工作交给与其关联的 TokenHandler 处理* @param text* @return*/
public String parse(String text) {if (text == null || text.isEmpty()) {return "";}// search open token// 查找openToken的位置int start = text.indexOf(openToken);if (start == -1) {return text;}char[] src = text.toCharArray();int offset = 0;final StringBuilder builder = new StringBuilder();StringBuilder expression = null;// 当存在openToken时,才继续处理while (start > -1) {if (start > 0 && src[start - 1] == '\\') {// this open token is escaped. remove the backslash and continue.builder.append(src, offset, start - offset - 1).append(openToken);offset = start + openToken.length();} else {// found open token. let's search close token.if (expression == null) {expression = new StringBuilder();} else {expression.setLength(0);}// 拼接从0到openToken之前的字符builder.append(src, offset, start - offset);// 设置offset值为openToken结束的位置offset = start + openToken.length();// 从offset值之后开始找第一个closeToken的位置int end = text.indexOf(closeToken, offset);// 如果存在,则继续处理while (end > -1) {if (end > offset && src[end - 1] == '\\') {// this close token is escaped. remove the backslash and continue.expression.append(src, offset, end - offset - 1).append(closeToken);offset = end + closeToken.length();// 继续查找当前closeToken之后的closeTokenend = text.indexOf(closeToken, offset);} else {expression.append(src, offset, end - offset);break;}}// 如果不存在if (end == -1) {// close token was not found.// 拼接剩余的字符builder.append(src, start, src.length - start);// 设置offset为字符数组的长度offset = src.length;} else {/*** DynamicCheckerTokenParser:如果存在,则设置当前SQL为动态的* BindingTokenParser:获取$变量的值* ParameterMappingTokenHandler:将#替换为?,并构建参数映射ParameterMapping*/builder.append(handler.handleToken(expression.toString()));// 设置offset值为closeToken结束的位置offset = end + closeToken.length();}}start = text.indexOf(openToken, offset);}// 拼接剩余的字符if (offset < src.length) {builder.append(src, offset, src.length - offset);}return builder.toString();
}

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

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

相关文章

notepad++ verilog关键字自动补全

新建verilog.xml放在安装目录下 D:\Program Files (x86)\Notepad\autoCompletion <?xml version"1.0" encoding"Windows-1252" ?> <NotepadPlus><AutoComplete><KeyWord name"accept_on" /><KeyWord name"a…

mysql自定义实体类框架

根据表结构自动生产实体类和方法,根据反射与io生成,可自定义扩展方法 package com.digital.web.front; /*** pom依赖* <dependency>* <groupId>mysql</groupId>* <artifactId>mysql-connector-java</artifactId>* <version>5.1.27</ve…

设计模式详解-责任链模式

类型&#xff1a;行为型模式 实现原理&#xff1a;为请求创建了一个接收者对象的链。对请求的发送者和接收者进行解耦&#xff0c;每个接收者都包含对另一个接收者的引用&#xff0c;如果一个对象不能处理该请求&#xff0c;那么它会把相同的请求传给下一个接收者&#xff0c;…

极致鸿蒙2.0——华为MatePad系列安装AidLux,一个自带vscode的Python编译环境

看着刚刚人入手的华为鸿蒙系统MatePad11平板&#xff0c;是如此的美轮美奂&#xff0c;但是总感觉少了点什么&#xff0c;少了点什么呢&#xff1f;是编程环境&#xff0c;我爱MatePad&#xff0c;也爱编程&#xff0c;那如果可以在MatePad上编程&#xff0c;会发生什么&#x…

SpringBoot、Java 使用 Jsoup 解析 HTML 页面

使用 Jsoup 解析 HTML 页面 什么是 Jsoup&#xff1f; Jsoup 是一个用于处理 HTML 页面的 Java 库&#xff0c;它提供了简单的 API&#xff0c;使得从 HTML 中提取数据变得非常容易。无论是获取特定标签的内容还是遍历整个页面的元素&#xff0c;Jsoup 都能轻松胜任。 如何使…

【ARM Linux 系统稳定性分析入门及渐进12 -- GDB内存查看命令 “x“(examine)】

文章目录 gdb 内存查看命令 examine 上篇文章&#xff1a;ARM Linux 系统稳定性分析入门及渐进11 – GDB( print 和 p 的使用| 和 &#xff1a;&#xff1a;的使用|ptype|{&#xff1c;type&#xff1e;} &#xff1c;addr&#xff1e; ) gdb 内存查看命令 examine examine是…

c语言——判断,判断是否是字母

//判断&#xff0c;判断是否是字母 #include<stdio.h> #include<stdlib.h> int main() {char c;printf("输入字符&#xff1a;");scanf("%c",&c);if((c>a&&c<z)||(c>A&&c<Z)) //a~z的ASCLL区间是97-122&…

【每日一题Day299】LC2235两整数相加

两整数相加【LC2235】 给你两个整数 num1 和 num2&#xff0c;返回这两个整数的和。 实现 class Solution {public int sum(int num1, int num2) {return num1 num2;} }复杂度 时间复杂度&#xff1a; O ( 1 ) \mathcal{O}(1) O(1)空间复杂度&#xff1a; O ( 1 ) \mathcal{O}…

Unity进阶–通过PhotonServer实现联网登录注册功能(客户端)–PhotonServer(三)

文章目录 Unity进阶–通过PhotonServer实现联网登录注册功能(客户端)–PhotonServer(三)前情提要客户端部分 Unity进阶–通过PhotonServer实现联网登录注册功能(客户端)–PhotonServer(三) 前情提要 单例泛型类 using System.Collections; using System.Collections.Generic; …

【C# 基础精讲】自定义异常类

自定义异常类是C#中异常处理的一种重要方式&#xff0c;它允许您创建具有自定义错误信息和处理逻辑的异常类型&#xff0c;以提高程序的可读性和可维护性。通过自定义异常类&#xff0c;您可以为特定的业务逻辑或应用场景创建更有意义的异常&#xff0c;使错误处理更加精确和有…

【Go 基础篇】Go语言关键字和预定义标识符解析:探索编程的基石与核心要素

介绍 在计算机编程中&#xff0c;关键字&#xff08;Keywords&#xff09;和预定义标识符&#xff08;Predefined Identifiers&#xff09;是编程语言的核心要素&#xff0c;它们在语法结构和语言功能中起到重要作用。在Go语言&#xff08;Golang&#xff09;中&#xff0c;关…

虚拟拍摄,如何用stable diffusion制作自己的形象照?

最近收到了某活动的嘉宾邀请&#xff0c;我将分享&#xff1a; 主题&#xff1a;生成式人工智能的创新实践 简要描述&#xff1a;从品牌营销、智能体、数字内容创作、下一代社区范式等方面&#xff0c;分享LLM与图像等生成式模型的落地应用与实践经验。 领域/研究方向&#xff…

1.flink快速入门

前言 下图表示的是一个简单的flink-job的计算图&#xff0c;这种图被称为DAG(有向无环图)&#xff0c;表示的这个任务的计算逻辑&#xff0c;无论是spark、hive、还是flink都会把用户的计算逻辑转换为这样的DAG&#xff0c;数据的计算按照DAG触发&#xff0c;理论上只要构建出…

[oneAPI] 使用字符级 RNN 生成名称

[oneAPI] 使用字符级 RNN 生成名称 oneAPI特殊写法使用字符级 RNN 生成名称Intel Optimization for PyTorch数据下载加载数据并对数据进行处理创建网络训练过程准备训练训练网络 结果 参考资料 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517…

3:Ubuntu上配置QT交叉编译环境并编译QT程序到Jetson Orin Nano(ARM)

1.Ubuntu Qt 配置交叉编译环境 1.1 ubuntu 20.04安装Qt sudo apt-get install qtcreator 1.2 配置QT GCC配置同上 最后配置Kits 上面设置完成之后 &#xff0c;设置Kits 中的Device(这是为了能够直接把项目部署到arm设备上) 点击NEXT之后会出现连接被拒绝&#xff0c;不用担…

函数极限与连续性——张宇老师学习笔记

Latex 源代码以及成品PDF&#xff08;Debug版本&#xff09;&#xff1a;https://wwsk.lanzouc.com/itaDI15vddcb Latex编译Debug版本&#xff1a; $ xelatex 函数极限与连续性.texLatex编译Relese版本&#xff08;无例题、习题&#xff0c;只有概念定义&#xff09;&#xf…

open cv学习 (十)图形检测

图形检测 demo1 # 绘制几何图像的轮廓 import cv2img cv2.imread("./shape1.png")gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图像二值化 t, binary cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)# 检测图像中的所有轮廓 contours, hierarchy cv2.f…

小程序 CSS-in-JS 和原子化的另一种选择

小程序 CSS-in-JS 和原子化的另一种选择 小程序 CSS-in-JS 和原子化的另一种选择 介绍快速开始 pandacss 安装和配置 0. 安装和初始化 pandacss1. 配置 postcss2. 检查你的 panda.config.ts3. 修改 package.json 脚本4. 全局 css 注册 pandacss5. 配置的优化与别名 weapp-pand…

Log4Qt日志框架(1)- 引入到QT中

Log4Qt日志框架&#xff08;1&#xff09;- 引入到QT中 1 下载源码2 简介3 加入到自己的项目中3.1 使用库文件3.2 引入源文件 4 说明 1 下载源码 github&#xff1a;https://github.com/MEONMedical/Log4Qt 官方(版本较老)&#xff1a;https://sourceforge.net/projects/log4q…

希望计算机专业同学都知道这些博主

湖科大教书匠——计算机网络 “宝藏老师”、“干货满满”、“羡慕湖科大”…这些都是网友对这门网课的评价&#xff0c;可见网课质量之高&#xff01;最全面的面试网站 湖南科技大学《计算机网络》微课堂是该校高军老师精心制作的视频课程&#xff0c;用简单的语言描述复杂的…