大意了,无用了MyBatis的$符号

news/2024/3/29 8:07:49/文章来源:https://blog.csdn.net/yi_chao_jiang/article/details/130155910

复盘

近期有一个小业务需求,非常简单,本质就是增加几个过滤参数,可以透传给数据库就可以了。

代码使用MyBatis作为ORM框架

原始SQL如下

<select id="listDevices" resultType="DeviceDO">select device_uuid as deviceUUID, client_type as clientTypefrom tb_deviceorder by gmt_modified desc
</select>

上面没有过滤条件,本次改造是增加client_type的过滤,由于可能存在多个client_type,故需要使用MyBatis的foreach用法构造in条件。当时偷了个懒,直接从现有代码库里面copy了一份做了改动。

第一版改造如下:

<select id="listDevices" resultType="DeviceDO">select device_uuid as deviceUUID, client_type as clientTypefrom tb_devicewhere client_type in <foreach collection="list" index="index" item="item" open="(" close=")" separator=",">${item}</foreach>order by gmt_modified desc
</select>

关于foreach用法可以参照:https://juejin.cn/post/6844903886575108110

自以为应该没有问题,就屁颠屁颠的部署服务到预发环境了,结果报错了。

MyBatis的异常:

Unknown column 'android' in 'where clause'] with root cause

奇怪,怎么会把android当做了列呢,这明明是查询条件才对。从日志里面又捞取了一下执行的SQL,终于发现端倪,原来传入到的条件并没有添加""。

select device_uuid as deviceUUID, client_type as clientType       
from tb_device
where client_type in  (android , iOS )
order by gmt_modified desc

那就再检查一下代码吧,把自己的代码和原来copy的代码仔细做了一下对比,并未发现异常,奇怪+1。

那就再检查一下对应的字段类型吧,发现原来正常工作的类型是int,所以即使不加引号也可以正常运行。但是这里的client_type是varchar类型,如果不加引号那就会报错。

所以问题来了,为什么没有添加引号呢? 还是检查一下MyBatis的Mapper文件,发现犯了一个巨大的错误,其他条件地方使用的是#+变量名,这里使用了$+变量名,那就替换一下吧。

更新后SQL:

<select id="listDevices" resultType="DeviceDO">select device_uuid as deviceUUID, client_type as clientTypefrom tb_devicewhere client_type in <foreach collection="list" index="index" item="item" open="(" close=")" separator=",">#{item}</foreach>order by gmt_modified desc
</select>

替换以后执行就正常了。

==>  Preparing: select device_uuid as deviceUUID, client_type as clientType from tb_device where client_type in ( ? , ? ) order by gmt_modified desc 
==> Parameters: android(String), iOS(String)
<==      Total: 0

延伸

关于MyBatis #和$的区别,可以参照一下这个https://segmentfault.com/a/1190000004617028

提取一下文章关键信息,mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析。

  • #{ } 解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,能使用#{ }的地方就用#{ }
  • ${ } 仅仅为一个纯碎的 string 替换,在动态 SQL 解析阶段将会进行变量替换,表名作为变量时,必须使用 ${ }。

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

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

相关文章

前端02:CSS选择器等基础知识

CSS基础选择器、设置字体样式、文本样式、CSS的三种引入方式、能使用Chrome调试工具调试样式 HTML专注做结构呈现&#xff0c;样式交给CSS&#xff0c;即结构&#xff08;HTML&#xff09;和样式CSS相分离 CSS主要由量分布构成&#xff0c;选择器以及一条或多条声明 选择器&…

18.Java泛型

目录 1. Java基本介绍 2. JDK下载安装及其环境配置 3. 一个简单的java程序 4. Eclipse基本使用、数据类型、运算符 5. 控制语句&#xff08;if、switch、for、while、foreach&#xff09; 6. Java数组 7. Java字符串对象(String|StringBuffer|StringBuilder|StringJoiner…

OFDM-LS信道估计 MMSE信道估计公式推导

假设ofdmN个子载波之间是完全正交的&#xff0c;即不考虑ICI影响&#xff0c;通过发送训练序列来实现信道估计。 其中&#xff0c;在推导6.8的时候&#xff0c;需要将6.6先拆解一下。 X − 1 Y X − 1 ( X H Z ) X − 1 X H X − 1 Z H X − 1 Z X^{-1}Y X^{-1}(XHZ)…

LeetCode213 打家劫舍 II 动态规划法

题目地址 https://leetcode.cn/problems/house-robber-ii/ 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 &#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装…

【Hive实战】探索Hive 2.X以及更早版本的MetaStore

探索Hive 2.X以及更早版本的MetaStore 文章目录 探索Hive 2.X以及更早版本的MetaStore概述配置元数据服务和元数据存储库基础配置参数其他配置参数默认配置配置元服务数据库使用内嵌模式的Derby库使用远程数据存储库 配置元数据服务本地/内嵌服务配置远程服务配置 元数据服务配…

【KingSCADA】什么是精灵图以及如何创建精灵图

大家好&#xff0c;我是雷工&#xff01; 本篇学习精灵图的制作&#xff0c;以下为学习内容及相关笔记。 一、什么是精灵图 精灵图是一种在外观上类似组合图&#xff0c;但内部嵌入了比较丰富的动画链接与逻辑控制&#xff0c;工程开发人员只要将其从精灵图库中调出来放置在开…

MySQL基础练习——创建数据库、数据表,并进行修改

目录 题目&#xff1a; 创建库和表&#xff1a; 创建库&#xff1a; 创建表&#xff1a; 将 c_contact 字段插入到 c_birth 字段后面&#xff1a; 将 c_name 字段数据类型改为VARCHAR(70)&#xff1a; 将 c_contact 字段改名为 c_phone&#xff1a; 将表名修改为 customer…

AD9208调试经验分享

背景概述 FMC137 是一款基于 VITA57.4 标准规范的 JESD204B 接口FMC 子 卡 模 块 &#xff0c; 该 模 块 可 以 实 现 4 路 14-bit 、 2GSPS/2.6GSPS/3GSPSADC 采集功能。该板卡 ADC 器件采用 ADI 公司的 AD9208 芯片&#xff0c;&#xff0c;与 ADI 公司的 AD9689 可以实现 …

量子力学 学习

对于同一个竖直向上量子比特&#xff0c;不对他进行任何的干扰&#xff0c;进行第一次水平测试实验会随机得到一个一或者负一&#xff0c;之后再进行多少次水平测试实验都与第一次的试验结果是相同的。 我们换用其他的竖直向上量子比特&#xff0c;或者对原来的量子比特进行干扰…

Matlab绘图中的一些技能

目录 1、matlab坐标轴设置多种字体(复合字体) 2、matlab图片中title生成的标题转移至图像下端 3、指定对应格式和期望dpi的图像进行保存、以及不留白保存 4、设置字体字号&#xff08;x、y轴&#xff0c;标题。全局字体等&#xff09; 5、设置刻度值信息&#xff0c;只有左…

引领文旅新体验!实时云渲染助力打造“永不落幕”的湾区文采会元宇宙

2022年11月25日至27日&#xff0c;2022年粤港澳大湾区公共文化和旅游产品&#xff08;东莞&#xff09;采购会&#xff08;简称“湾区文采会”&#xff09;在广东省东莞市文化馆举行。 文采会期间&#xff0c;文采会元宇宙线上虚拟展厅全新亮相&#xff0c;这艘承载着科技与文化…

5款十分小众的软件,知道的人不多但却很好用

今天推荐5款十分小众的软件&#xff0c;知道的人不多&#xff0c;但是每个都是非常非常好用的&#xff0c;有兴趣的小伙伴可以自行搜索下载。 1.视频直播录制——OBS Studio OBS Studio可以让你轻松地录制和直播你的屏幕、摄像头、游戏等内容。你可以使用OBS Studio来创建多种…

Mysql设置表只存储一段时间的数据

使用MySQL的事件调度器&#xff08;Event Scheduler&#xff09;来定期删除表中的数据。 假设你要删除的表是mytable&#xff0c;并且表中有一个名为created_at的日期时间类型的列&#xff0c;存储了每条记录的创建时间。你可以通过以下步骤设置表只存储30天的数据&#xff1a…

机器学习 协同过滤算法

协同过滤算法 协同过滤算法是根据已有的数据来推测出未知的数据&#xff0c;从海量的数据中找到相似度达到指定范围的数据&#xff0c;而这些数据成为你的邻居&#xff0c;系统将会为你推荐心仪的物品。 余弦相似法 通过计算两个向量的夹角余弦值来评估它们的相似度 修正余弦…

《站在巨人的肩膀上学习Java》

Java从诞生距今已经有28年了&#xff0c;在这段时间里&#xff0c;随着Java版本的不断迭代&#xff0c;Java新特性的不断出现&#xff0c;使得Java被使用的越来越广泛。在工程界Java语言一直是大家最喜欢的语言之一&#xff0c;Java一直排行在编程语言热门程度的前3名。 可想而…

从0搭建Vue3组件库(六):前端流程化控制工具gulp的使用

随着前端诸如webpack&#xff0c;rollup&#xff0c;vite的发展&#xff0c;gulp感觉似乎好像被取代了。其实并没有&#xff0c;只不过它从台前退居到了幕后。我们仍然可以在很多项目中看到它的身影&#xff0c;比如elementplus、vant等。现在gulp更多的是做流程化的控制。 比如…

delta.io 参数 spark.databricks.delta.replaceWhere.constraintCheck.enabled

总结 默认值true 你写入的df分区字段必须全部符合覆盖条件 .option("replaceWhere", "c2 == 2") false: df1 overwrite tb1: df1中每个分区的处理逻辑: - tb1中存在(且谓词中匹配)的分区,则覆盖 - tb1中存在(谓词中不匹配)的分区,则append - tb1中不存…

今天试了试chatgpt

今天试了试chatgpt&#xff0c;真是服了 arcade&#xff1f; Arcade是一个Python游戏开发库&#xff0c;它提供了一系列的工具和函数&#xff0c;可以帮助开发者快速地创建2D游戏。以下是Arcade的一些特点&#xff1a; 简单易用&#xff1a;Arcade提供了简单易用的API&#x…

Android分屏流程分析

本文基于Android 11。 SystemUI模块中的Divider管理着所有关于分屏的对象&#xff1a; DividerView&#xff08;分屏分割线&#xff0c;分屏显示界面&#xff09;SplitScreenTaskOrganizer&#xff08;分屏Task组织者&#xff0c;分屏逻辑&#xff09; 这里重点关注分屏逻辑…

Qt如何生成dump文件和pdb文件并进行调试定位

在main文件中增加下面代码用于可生成dump文件 #include "widget.h" #include <QApplication> #include <QDir> #include <QDateTime> #ifdef Q_OS_WIN#include <windows.h>#include <dbghelp.h> #endifstatic LONG WINAPI exceptionC…