MyBatis进行模糊查询时SQL语句拼接引起的异常问题
项目场景:
CRM项目,本文遇到的问题是在实现根据页面表单中输入条件,在数据库中分页模糊查询数据,并在页面分页显示的功能时,出现的“诡异”bug。
开发环境如下:
操作系统:Windows11
Java:jdk-21.0.2
IDE:eclipse 2024-3R
Tomcat:apache-tomcat-10.1.11
Maven:apache-maven-3.9.6
数据库:MariaDB11.0
项目地址:https://gitcode.com/weixin_44803446/crm-project.git
问题描述
在项目中,通过一下两个查询,分别查询对象列表跟总条数,通过日期查询及空条件查询结果均无异常,但是在通过名称及所有者名称进行模糊查询时,返回的查询结果为0,即使是全字段匹配也无法正常查询到想要的数据,Mapper文件片段如代码所示:
<!-- 通过条件查询市场活动表 --><select id="selectActivityListByConditionForPage" parameterType="map" resultMap="BaseResultMap">select a.id, a.name, u1.name as owner, a.start_date, a.end_date, a.cost, u2.name as create_by, a.create_timefrom tbl_activity ajoin tbl_user u1 on a.owner = u1.idjoin tbl_user u2 on a.create_by = u2.id<where><if test="name != null and name !=''">and a.name like '%'#{name}'%' </if><if test="owner != null and owner != ''"> and u1.name like '%'#{owner}'%' </if><if test="startDate != null and startDate != ''"> and a.start_date >= #{startDate}</if><if test="endDate != null and endDate != ''"> and a.end_date <= #{endDate} </if></where>order by a.create_time desclimit #{beginNo},#{pageSize}</select><!-- 查询对应条件下的市场活动总条数 --><select id="selectActivityCounts" parameterType="map" resultType="int">select count(*)from tbl_activity ajoin tbl_user u1 on a.owner = u1.idjoin tbl_user u2 on a.create_by = u2.id<where><if test="name != null and name !=''">and a.name like '%'#{name}'%' </if><if test="owner != null and owner != ''"> and u1.name like '%'#{owner}'%' </if><if test="startDate != null and startDate != ''"> and a.start_date >= #{startDate}</if><if test="endDate != null and endDate != ''"> and a.end_date <= #{endDate} </if></where></select>
原因分析:
- 首先,确定前端的字段是否完整的传递到Controller,通过Console.log(参数)的方式将参数打印在浏览器控制台中,经过验证参数传递无异常;
- 其次,在Controller及Service中获取参数并打印,确保参数传递过程没有缺失等;
- 查看查询日志:
JDBC Connection [org.mariadb.jdbc.Connection@5516cc8d] will be managed by Spring
==> Preparing: select a.id, a.name, u1.name as owner, a.start_date, a.end_date,a.cost, u2.name as create_by, a.create_time from tbl_activity a join tbl_user u
1 on a.owner = u1.id join tbl_user u2 on a.create_by = u2.id WHERE a.name like '
%'?'%' order by a.create_time desc limit ?,?
==> Parameters: n(String), 0(Integer), 10(Integer)
<== Total: 0
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSq
lSession@2ef7efff]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.def
aults.DefaultSqlSession@2ef7efff]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.
defaults.DefaultSqlSession@2ef7efff]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaul
ts.DefaultSqlSession@2ef7efff]
Creating a new SqlSession
Registering transaction synchronization for SqlSession [org.apache.ibatis.sessio
n.defaults.DefaultSqlSession@66e3b3d0]
JDBC Connection [org.mariadb.jdbc.Connection@b60a270] will be managed by Spring
==> Preparing: select count(*) from tbl_activity a join tbl_user u1 on a.owner
= u1.id join tbl_user u2 on a.create_by = u2.id WHERE a.name like '%'?'%'
==> Parameters: n(String)
<== Columns: count(*)
<== Row: 0
<== Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSq
lSession@66e3b3d0]
Transaction synchronization committing SqlSession [org.apache.ibatis.session.def
aults.DefaultSqlSession@66e3b3d0]
Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.
defaults.DefaultSqlSession@66e3b3d0]
Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaul
ts.DefaultSqlSession@66e3b3d0]
由数据库查询日志可以看出,在执行模糊查询时,参数准确无误的传递到了Sql语句中,但是经过模糊查询后,查到的数量Total为0,但是实际上数据库中是有一条符合模糊条件的数据的。
猜想:
<if test="name != null and name !=''">and a.name like '%'#{name}'%'
</if>
这一句模糊查询语句有问题,尝试在’%‘与#{name} 之间加上空格后重启服务器测试,发现模糊查询功能正常。问题就出在MyBatis在处理字符串拼接时,如果以’%‘#{name}’%’ 这样紧密的格式书写,则会导致其将整个字段识别为一个整体,最终的拼接体可能为%‘#{name}’%。
解决方案:
- 通过在#{name}前后添加空格,让MyBatis正确的识别并拼接参数与字符串;
- 更严谨的方式是使用CONCAT函数,通过CONCAT()函数将"%" 与#{name}拼接起来,这样避免了因为拼写错误等原因导致最终SQL与我们预想的不一致的情况。
<!-- 通过条件查询市场活动表 --><select id="selectActivityListByConditionForPage" parameterType="map" resultMap="BaseResultMap">select a.id, a.name, u1.name as owner, a.start_date, a.end_date, a.cost, u2.name as create_by, a.create_timefrom tbl_activity ajoin tbl_user u1 on a.owner = u1.idjoin tbl_user u2 on a.create_by = u2.id<where><if test="name != null and name !=''">and a.name like concat('%',#{name},'%')</if><if test="owner != null and owner != ''"> and u1.name like concat('%', #{owner},'%' )</if><if test="startDate != null and startDate != ''"> and a.start_date >= #{startDate}</if><if test="endDate != null and endDate != ''"> and a.end_date <= #{endDate} </if></where>order by a.create_time desclimit #{beginNo},#{pageSize}</select><!-- 查询对应条件下的市场活动总条数 --><select id="selectActivityCounts" parameterType="map" resultType="int">select count(*)from tbl_activity ajoin tbl_user u1 on a.owner = u1.idjoin tbl_user u2 on a.create_by = u2.id<where><if test="name != null and name !=''">and a.name like concat('%',#{name},'%')</if><if test="owner != null and owner != ''"> and u1.name like concat('%', #{owner},'%' )</if><if test="startDate != null and startDate != ''"> and a.start_date >= #{startDate}</if><if test="endDate != null and endDate != ''"> and a.end_date <= #{endDate} </if></where></select>
相关文章:
MyBatis进行模糊查询时SQL语句拼接引起的异常问题
项目场景: CRM项目,本文遇到的问题是在实现根据页面表单中输入条件,在数据库中分页模糊查询数据,并在页面分页显示的功能时,出现的“诡异”bug。 开发环境如下: 操作系统:Windows11 Java&#…...
网站调用Edge浏览器API:https://api-edge.cognitive.microsofttranslator.com/translate
Edge浏览器有自带的翻译功能,在运行pc项目可能会遇到疯狂调用Edge的API https://api-edge.cognitive.microsofttranslator.com/translate 这个URL(https://api-edge.cognitive.microsofttranslator.com/translate)指向的是微软服务中的API接…...
css实现优惠券样式
实现优惠券效果: 实现思路: 需要三个盒子元素,使用 css 剪裁,利用 ellipse 属性,将两个盒子分别裁剪成两个半圆,位置固定在另一个盒子元素左右两边适当位置上。为另一个盒子设置想要的样式,圆角…...
函数递归(C语言)(详细过程!)
函数递归 一. 递归是什么1.1 递归的思想1.2 递归的限制条件 二. 递归举例2.1 求n的阶乘2.2 按顺序打印一个整数的每一位 三. 递归与迭代3.1 求第n个斐波那契数 一. 递归是什么 递归是学习C语言很重要的一个知识,递归就是函数自己调用自己,是一种解决问题…...
uniapp 接口请求封装
根目录下创建 config目录 api.js request.js // request.js // 封装一个通用的网络请求函数 适当调整 function httpRequest(options) {const userToken uni.getStorageSync(access_token).token;return new Promise((resolve, reject) > {uni.request({url: ${options.ur…...
C++中的观察者模式
目录 观察者模式(Observer Pattern) 实际应用 股票价格监控系统 发布-订阅系统 总结 观察者模式(Observer Pattern) 观察者模式是一种行为型设计模式,它定义了对象间的一对多依赖关系。当一个对象的状态发生改变…...
conda虚拟环境,安装pytorch cuda cudnn版本一致,最简单方式
1、pytorch版本安装(卸载也会有问题) (1)版本如何选择参考和卸载 https://zhuanlan.zhihu.com/p/401931724 (2)对应版本如何安装命令 https://pytorch.org/get-started/previous-versions/ 最简答安装参考…...
第 5 章:面向生产的 Spring Boot
在 4.1.2 节中,我们介绍了 Spring Boot 的四大核心组成部分,第 4 章主要介绍了其中的起步依赖与自动配置,本章将重点介绍 Spring Boot Actuator,包括如何通过 Actuator 提供的各种端点(endpoint)了解系统的…...
在 Windows 操作系统中,可以通过命令行工具来杀死进程
1. 使用 taskkill 命令 taskkill 命令是一个用于终止进程的命令行工具,可以通过进程名称或进程 ID (PID) 来杀死进程。 按进程名称杀死进程 taskkill /IM processname.exe /Fprocessname.exe 是进程的名称。/F 参数表示强制终止进程。 例如,终止名为…...
uni-app文件下载 h5 xls 乱码 锟斤拷 Blob pdf打不开
原先下载方式,PC管理端和浏览器打开文件能下载,xls没出现乱码,pdf能正常显示,H5下载xls乱码锟斤拷,PDF显示空白内容 怀疑是前端问题,也尝试过修改后端代码 后端设置编码格式 response.setCharacterEncoding(characte…...
Vue25-内置指令02:v-text指令
一、v-html对比v-text v-html支持结构的解析,v-text不支持结构的解析。 二、v-html的安全性问题 2-1、cookie的原理(node.js) 7天免登录,cookie实现。 cookie的本质就是类似于json的字符串,格式是:key-va…...
stable diffusion中的negative prompt是如何工作的
https://stable-diffusion-art.com/how-negative-prompt-work/https://stable-diffusion-art.com/how-negative-prompt-work/https://zhuanlan.zhihu.com/p/644879268...
STM32项目分享:智能小区充电桩系统
目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 1.PCB图 2.PCB板打样焊接图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片: 哔哩哔哩视频链接: https://www.bilibili.c…...
PDU模块中浪涌保护模块与空开模块的应用
由于PDU具体应用的特殊性,其在规划设计时具有应用场景的针对性,同时PDU的高度定制化的特点,是其他电气联接与保护产品所不具备的。 PDU基础的输出输入功能外,其电路的控制与电压保护器同时也极为重要。空气开关和浪涌保护器相关功…...
19、Go Gin框架集成Swagger
介绍: Swagger 支持在 Gin 路由中使用一系列注释来描述 API 的各个方面。以下是一些常用的 Swagger 注释属性,这些属性可以在 Gin 路由的注释中使用: Summary: 路由的简短摘要。Description: 路由的详细描述。Tags: 用于对路由进行分类的标…...
自动同步库数据——kettle开发36
kettle中的那些人工智能。 一、kettle的AI能力目录 跨库同步 2.自动开发 3.自动优化 二、AI实例 1、跨库同步 sqlsever表同步至oracle数据库 1.1源库sqlserver 1.2目标库oracle 1.3可视化跨库同步 使用多表复制向导 选择跨库的表,下一步下一步,即可…...
MSOCache在电脑中可以删除吗?
MSOCache文件夹在电脑中是可以删除的。但删除前需要了解以下几点: MSOCache文件夹的作用: MSOCache文件夹是Microsoft Office的本地安装源,用于存储Office安装和更新过程中所需的临时文件,如安装程序所需的组件、配置设置以及更新…...
数据网格和视图入门
WinForms数据网格(GridControl类)是一个数据感知控件,可以以各种格式(视图)显示数据。本主题包含以下部分,这些部分将指导您如何使用网格控件及其视图和列(字段)。 Grid Control’s…...
雨的轮回与生命的律动
雨的轮回与生命的律动 我们生活在一个充满变数的世界里,许多事情无法预测,如同这不知何时会停歇的雨。然而,尽管我们无法预知雨停的确切时刻,但我们深知,这场雨终将会过去,阳光终将再次洒满大地。这种对未…...
CANopen for Python 使用教程(二)
系列文章目录 前言 CANopen 标准的 Python 实现。该项目的目的是在一个简单的 Pythonic 接口中支持 CiA 301 标准中最常见的部分。它主要针对测试和自动化任务,而不是符合标准的主实施。 该库支持 Python 3.6 及以上版本。 一、特点 该库主要用作主库。 NMT 主站…...
从零构建高性能云原生抓取平台:架构、部署与实战指南
1. 项目概述:从零到一构建一个高性能云原生抓取平台最近在折腾一个很有意思的开源项目,叫openperf/openclaw-cloud。乍一看这个名字,可能有点摸不着头脑,但如果你拆解一下,就能发现它的野心不小。“OpenPerf”暗示了其…...
泊松分布实战指南:从原理到异常检测的工程落地
1. 什么是泊松分布?——一个数据从业者每天都在用、却未必真正吃透的概率工具你有没有算过,过去一小时里你的邮箱收到了几封新邮件?上个月车间里产线上出现了几个次品?过去24小时网站服务器收到了多少次API请求?这些数…...
LLM推理服务调度优化:KV$缓存与负载均衡的乘法组合方法
1. LLM推理服务调度优化概述大型语言模型(LLM)推理服务面临的核心挑战之一是如何高效调度用户请求。当多个用户同时向部署在GPU集群上的LLM服务发送请求时,调度系统需要决定将每个请求分配给哪个计算实例。这个决策直接影响两个关键性能指标:首令牌延迟(…...
CAD2025详细安装教程图文版
一、安装环境建议AutoCAD 2025 建议使用 Windows 10/11 64位系统,电脑配置建议 i5 以上处理器、16GB 以上内存、SSD 固态硬盘,并预留足够磁盘空间。安装前关闭杀毒软件,保持系统组件完整,避免因运行库缺失导致安装失败。二、安装步…...
TypeScript HTTP客户端clientele:声明式API与全链路类型安全实践
1. 项目概述:一个现代、类型安全的HTTP客户端库在构建现代应用程序时,与外部API进行通信几乎是每个开发者都会遇到的日常任务。无论是调用一个天气服务、与支付网关交互,还是从内部微服务获取数据,你都需要一个可靠、高效且易于维…...
如何为你的Python项目接入多个大模型API并统一管理调用
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 如何为你的Python项目接入多个大模型API并统一管理调用 在开发基于大语言模型的AI应用时,开发者常常面临一个选择&…...
AI赋能电弧故障检测:从原理到工程落地的关键技术解析
1. 项目概述:当AI遇见电弧故障,一场配电安全的静默革命作为一名在电力系统一线摸爬滚打了十几年的工程师,我亲眼见过太多因电弧故障引发的惨痛事故。从设备烧毁到火灾,甚至人身伤害,这些“电火花”的破坏力远超常人想象…...
传统密码协议(秘密共享协议)
在现代密码学领域,密码协议扮演着至关重要的角色,用于确保消息在传输和处理过程中的安全性和完整性。本栏目将深入讨论多种密码协议的细节和应用,从基础的鉴别和密钥交换,到秘密共享和不经意传输等。此外,还将研究如何…...
AI、VR、AR与元宇宙在人力资源管理中的融合应用与落地实践
1. 项目概述:当HR遇见未来科技最近和几位做人力资源的朋友聊天,发现一个挺有意思的现象:大家嘴上都在聊数字化转型,但一提到AI、VR这些具体技术,很多人第一反应还是“那是IT部门的事”或者“听起来很酷,但离…...
CANN pi0机器人VLA大模型昇腾推理指南
pi0机器人VLA大模型昇腾使用指南 【免费下载链接】cann-recipes-embodied-intelligence 本项目针对具身智能业务中的典型模型、加速算法,提供基于CANN平台的优化样例 项目地址: https://gitcode.com/cann/cann-recipes-embodied-intelligence pi0整体介绍 论…...
