mybatis组件SqlSource的种类

news/2025/3/24 18:36:09/文章来源:https://www.cnblogs.com/shenxingzhuge/p/18787560

SqlSource是mybatis重要的组件,是对你写的sql语句的简单封装。

 

public interface SqlSource {BoundSql getBoundSql(Object parameterObject);}

这个接口有很多种实现:

 

 VelocitySqlSource这个实现类是一个测试。实际上mybatis根本就不会使用这个实现类。

那么在mybatis内部是在哪一步创建SqlSource的呢?那就是在解析我们写的一些sql标签时生成的,在解析sql标签的时候会生成MappedStatement对象,这个对象包含了你写的sql标签所有的内容,也包括sql语句的基本信息,sql语句的基本信息就封装成了SqlSource对象。源码在这个方法:org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode。

创建SqlSource是由LanguageDriver对象来创建的,这个对象其实也可以在我们写的sql标签中配置,只是我们实际开发不会去自定义这个对象。

 

public class MyLanguageDriver implements LanguageDriver {@Overridepublic ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {return null;}@Overridepublic SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {return null;}@Overridepublic SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {return null;}
}

 

那么mybatis默认生成的就是XMLLanguageDriver。那么这个对象创建的SqlSource就两种。一种是DynamicSqlSource,还有一种是RawSqlSource。

 public SqlSource parseScriptNode() {MixedSqlNode rootSqlNode = parseDynamicTags(context);SqlSource sqlSource;if (isDynamic) {sqlSource = new DynamicSqlSource(configuration, rootSqlNode);} else {sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);}return sqlSource;}

 

DynamicSqlSource很好理解,那就是你的sql是动态的,那么就会生成这个对象。如果不是动态的就生成RawSqlSource。

动态sql就比如你的sql语句的where是用<where>标签生成的,包括<if test> 标签,还包括$符号这种sql语句的拼接。然后除了这些情况就会生成RawSqlSource。

但是RawSqlSource其实还包了一层SqlSource对象。

 

我可以告诉大家,他里面的SqlSource最终生成的就是StaticSqlSource对象。而且这个StaticSqlSource中的sql已经是带?的sql了,也就是将你的#{}替换成了?

public class StaticSqlSource implements SqlSource {/*** 带?的sql*/private final String sql;

 

那么现在我们已经了解到了三个SqlSource的实现。离最后的真相还差一个ProviderSqlSource。这个SqlSource很有意思,想要生成的SqlSource是他。那么你的sql写法也很有意思,不能通过传统的sql标签来实现,也不能用@Slelect 或者其他注解来实现。而是有一种专门的写法来实现。

首先写一个类,这个类中有个方法来返回一个sql,这个sql当然跟你的业务有关。

public class FatherSqlProvider {/*** @param username sql执行所需要的参数* @return*/public String findByUsername(String username) {return "select * from father where username = " + "#{username}";}
}

 

然后在你的mapper接口层使用他

@SelectProvider(type= FatherSqlProvider.class,method = "findByUsername")List<Father> selectByUsername(String username);

 

那么这种写法最终生成的SqlSource就是ProviderSqlSource。我来debug源码来揭露真相。

源码入口在这个方法了:org.apache.ibatis.builder.annotation.MapperAnnotationBuilder#parse,在这个方法后面会对你的mapper接口的方法进行遍历,也就是解析mapper方法上的相关注解。但是mybatis很可惜的是不支持你在mapper方法上自定义注解,但是可以通过拦截器来实现。好,扯多了,看源码:

/*** 这里就是遍历dao接口中所有的方法,然后获取方法上的注解进行解析* mybatis是支持用注解的方式对MySQL进行crud的。但是实际开发都用映射文件*/for (Method method : type.getMethods()) {if (!canHaveStatement(method)) {continue;}if (getAnnotationWrapper(method, false, Select.class, SelectProvider.class).isPresent()&& method.getAnnotation(ResultMap.class) == null) {parseResultMap(method);}try {//最终会在这里创建SqlSource对象
          parseStatement(method);} catch (IncompleteElementException e) {configuration.addIncompleteMethod(new MethodResolver(this, method));}}

 

继续跟进parseStatement方法

 

真相大白:

好了,到这结束,说实话,暂时没啥用。尤其是这种sql写法,谁要是开发这么写,就等着被领导夸奖吧。

 

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

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

相关文章

静雅斋目录2

托管于国内企业顶想云的使用目录前情概要 本来已经有一个使用目录了,但是实在是受不了 GitHub 时不时卡壳的表现,就重新启用这个国内的搜索目录,外观要稍微差一点,但使用体验要好得多。 托管地址 托管于 顶想云 平台的目录样式 .编辑地址:顶想云.iframe-container { /* 容…

ARP高级欺骗-配置路由转发

引出问题: 当我们发起一次ARP欺骗之后,目标主机会出现断网情况。这种很容易就会被目标主机A发现。那我们怎么让目标主机发现不了自己被ARP欺骗了呢?问题描述: 1.受害主机A断网: 当目标主机A上网时,会进行TCP的连接,但是因为ARP欺骗之后,主机A的路由转发到的是主机B而不…

使用XIAO ESP32C6, XIAO扩展板和SHT31温湿度传感器构建温湿度计

我很高兴与您分享我的最新项目:我使用XIAO ESP32C6, XIAO扩展板和SHT31温湿度传感器构建的DIY温湿度计。我的目标是创造一种设备,可以帮助我监测家里的湿度水平,特别是因为我住在沿海热带地区,那里的湿度波动很大。这个想法来自于我需要保持一个舒适的室内环境。有时空气会…

可视化图解算法:判断一个链表是否为回文结构(回文链表)

对于链表的相关操作,我们总结了一套【可视化+图解】方法,依据此方法来解决链表相关问题,链表操作变得易于理解,写出来的代码可读性高也不容易出错。1. 题目 描述 给定一个链表,请判断该链表是否为回文结构。 回文是指该字符串正序逆序完全一致。 数据范围: 链表节点数 0≤…

使用ESP32和Gemini REST API语音输入调用带有自定义参数的函数

我们在建造什么? 在之前的教程中,我介绍了如何通过REST将ESP32连接到谷歌Gemini API以发送音频文件并对其进行转录。在本教程中,我将扩展到实际使用录制的音频而不是转录它-在这种情况下,打开和关闭LED环,加上根据语音命令改变LED的颜色。虽然我只是在操纵一个LED环,但你…

20244211 实验一《Python程序设计》实验报告

20244211 2024-2025-2 《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2442 姓名: 朱睿颖 学号:20244211 实验教师:王志强老师 实验日期:2025年3月18日 必修/选修: 专业选修课 1.实验内容熟悉Python开发环境; 练习Python运行、调试技能; 编写程序,练习…

JTS 介绍

JTS 是一个用于创建和操作向量几何的Java库;本文主要介绍其基本概念及使用,文中所使用到的软件版本:Java 1.8.0_341、JTS 1.20.0。 1、简介 LocationTech JTS 拓扑套件™(JTS)是一个开源的 Java 软件库,提供了平面几何的对象模型以及一套基础的几何函数。JTS 遵循开放 GI…

【笔记】力扣 134. 加油站——贪心

134. 加油站 中等 在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 给定两个整数数组 gas 和 cost ,如果你可以按顺…

2025.3.23 鲜花

[省选联考 2025] 追忆 题解[省选联考 2025] 追忆 题解hello (bpm) 2025恭喜获得 最速被击破奖🏆不会 bitset,赛时想不到分块也是没救了。 首先必然要坚定 bitset 信念,因为其严格难于导出子图。 维护后继直接 bitset 就是 \(\frac{nm}w\) 的。 考虑到第二个限制 \(l, r\) 如…

给wordpress文章提供在线翻译和朗读的功能

之前有一个用wordpress搭的英文站点,我想给文章每个段落下面加两个“朗读”和“翻译”的按钮,方便英语不好的浏览者快速的了解中文意思和读法。 下面给出实现思路,全部是deepseek给出的代码实现的。 1、在(functions.php)文件末尾加上如下代码function enqueue_custom_scrip…

第五章 影响估算的因素

对软件项目产生影响的因素,可以有多种分类方式。了解这些影响因素有助于提高估算的准确度,并改善对软件项目动态特性的整体理解。 影响到项目工作量、成本和进度的最具决定性的因素毫无疑问是项目的规模。其次是正在开发的软件的类型,紧随其后的是人员因素。开发中使用的编程…

2025.3.25(周二)

4、航空服务查询问题:根据航线,仓位,飞行时间查询航空服务。 假设一个中国的航空公司规定:① 中国去欧美的航线所有座位都有食物供应,每个座位都可以播放电影。② 中国去非欧美的国外航线都有食物供应,只有商务仓可以播放电影。③ 中国国内的航班的商务仓有食物供应,但是…