MyBatis 动态 SQL 使用详解
🌟 一、什么是动态 SQL?
动态 SQL 是指根据传入参数,动态拼接生成 SQL 语句,不需要写多个 SQL 方法。MyBatis 提供了 <if>
、<choose>
、<foreach>
、<where>
等标签来实现这类操作
✅ 二、动态 SQL 的优点
优点 | 说明 |
---|---|
✔️ 灵活 | 同一个 SQL 根据不同参数拼接不同条件(if / where),非常适合查询页面 |
✔️ 减少代码重复 | 比如模糊搜索功能,不再需要写多个 SQL 接口方法 |
✔️ 可读性强(配合 XML) | 结构清晰,尤其用 <where> / <set> / <foreach> |
✔️ SQL 控制权在开发者手中 | 和 Hibernate/JPA 相比,MyBatis 更易于优化复杂 SQL |
✔️ 易于维护多条件组合查询 | 如管理后台的搜索表单、动态筛选等功能 |
❌ 三、动态 SQL 的缺点
缺点 | 说明 |
---|---|
❌ 编写略繁琐 | XML 写法需要嵌套多个标签,容易出错,特别是嵌套复杂条件时 |
❌ 可读性下降(过度嵌套) | 动态 SQL 太复杂时,XML 显得臃肿不易读 |
❌ 不利于 IDE 自动提示 | 逻辑写在 XML 中,IDE 很难做类型检查和智能提示 |
❌ SQL 拼接错误不易发现 | 某些条件组合可能拼错 SQL,运行期才报错 |
❌ 与注解风格冲突 | 注解方式不支持复杂的动态 SQL,只能用 XML 实现动态拼接 |
🛠️ 四、动态 SQL 适用场景
✅ 最适合的场景:
场景 | 举例 |
---|---|
🔍 条件查询页面 | 多条件组合搜索,如:用户列表查询、订单筛选、日志检索 |
📋 后台管理系统 | 如 admin 页面支持 name、status、时间区间等动态条件 |
📊 报表查询系统 | 查询维度、范围、排序条件全是动态的 |
🧩 批量操作 | 如 IN 查询、批量更新、删除(用 <foreach> ) |
📌 多字段更新 | UPDATE 语句中字段非空才更新(用 <set> 标签) |
❌ 不推荐使用的场景:
场景 | 原因 |
---|---|
常规增删改查 | 逻辑简单,不需要动态拼接 |
SQL 条件固定 | 写死 SQL 语句更清晰、维护方便 |
条件复杂但变化不大 | 建议写多个 SQL 方法,避免 XML 太臃肿 |
🔍 五、小结一张表
点评维度 | 动态 SQL 表现 |
---|---|
灵活性 | ⭐⭐⭐⭐⭐ 超高 |
编写复杂度 | ⭐⭐⭐❌ 中等偏高 |
可维护性 | ⭐⭐⭐ 中等 |
性能控制 | ⭐⭐⭐⭐⭐ 好 |
推荐场景 | 多条件查询、批量操作 |
✨ 示例对比
✅ 使用动态 SQL:
<select id="searchUser" resultType="User">SELECT * FROM user<where><if test="name != null"> AND name LIKE CONCAT('%', #{name}, '%')</if><if test="age != null"> AND age = #{age}</if></where>
</select>
❌ 不使用动态 SQL(需要写多个方法):
<select id="findByName" ...>SELECT * FROM user WHERE name = #{name}</select>
<select id="findByAge" ...>SELECT * FROM user WHERE age = #{age}</select>
<select id="findByNameAndAge" ...>SELECT * FROM user WHERE name = #{name} AND age = #{age}</select>
🧩 MyBatis 动态 SQL 标签速查表
标签 | 作用 | 示例 | 注意事项 |
---|---|---|---|
<if> | 条件判断 | <if test="name != null">AND name = #{name}</if> | test 支持 OGNL 表达式,如 != null && name != '' |
<choose> <when> <otherwise> | 分支选择(类似 switch-case) | 见下方示例 | 只能命中一个 <when> ,类似 if…else |
<trim> | 自定义前缀、后缀、去掉多余的分隔符 | `<trim prefix=“WHERE” prefixOverrides="AND | OR "> … ` |
<where> | 自动加 WHERE 并去掉首个 AND/OR | <where><if test="...">AND ...</if></where> | 自动处理空条件时避免语法错误 |
<set> | 自动加 SET 并去掉多余逗号(用于 UPDATE) | <set><if test="...">name=#{name},</if></set> | 适用于动态更新字段 |
<foreach> | 遍历集合,构造 IN 语句、批量插入等 | 见下方示例 | 支持 list、array、Map,常用于 IN (...) |
<bind> | 创建一个变量,可用于字符串拼接等 | <bind name="pattern" value="'%' + name + '%'" /> | 常配合模糊查询使用 |
📚 示例合集
1️⃣ <if>
使用示例
<select id="selectUser" resultType="User">SELECT * FROM user<where><if test="name != null and name != ''">AND name LIKE CONCAT('%', #{name}, '%')</if><if test="age != null">AND age = #{age}</if></where>
</select>
2️⃣ <choose>
/ <when>
/ <otherwise>
示例
<select id="selectUser" resultType="User">SELECT * FROM user<where><choose><when test="name != null">AND name = #{name}</when><when test="age != null">AND age = #{age}</when><otherwise>AND status = 'active'</otherwise></choose></where>
</select>
3️⃣ <trim>
示例(手动 WHERE 拼接)
<select id="selectUser" resultType="User">SELECT * FROM user<trim prefix="WHERE" prefixOverrides="AND |OR "><if test="name != null">AND name = #{name}</if><if test="age != null">AND age = #{age}</if></trim>
</select>
4️⃣ <set>
示例(动态更新)
<update id="updateUser">UPDATE user<set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if></set>WHERE id = #{id}
</update>
5️⃣ <foreach>
示例(IN 查询)
<select id="selectByIds" resultType="User">SELECT * FROM user WHERE id IN<foreach collection="idList" item="id" open="(" separator="," close=")">#{id}</foreach>
</select>
语法片段 | 含义 |
---|---|
id="selectByIds" | 这是 Mapper 接口中方法对应的 SQL ID |
resultType="User" | 查询结果会映射成 User 类 |
collection="idList" | 传入的是一个集合参数名,比如一个 List<Integer> 类型的参数 |
item="id" | 遍历集合中的每个元素,当前元素命名为 id |
open="(" | 拼接 SQL 时,开头加一个左括号 ( |
separator="," | 每个参数之间用逗号隔开 |
close=")" | 最后一个参数后加上右括号 ) |
#{id} | 当前遍历元素的值,作为 SQL 参数传入(防 SQL 注入) |
6️⃣ <bind>
示例(模糊搜索)
<select id="searchByName" resultType="User"><bind name="pattern" value="'%' + name + '%'" />SELECT * FROM user WHERE name LIKE #{pattern}
</select>
部分 | 解释 |
---|---|
<select id="searchByName"> | 定义一个 SQL 查询方法,ID 是 searchByName |
resultType="User" | 查询结果会封装成 User 对象 |
<bind name="pattern" value="'%' + name + '%'"/> | MyBatis 提供的 <bind> 标签: 动态创建一个变量 pattern ,它的值是 '%xxx%' 这样的字符串,供后面 SQL 使用 |
value="'%' + name + '%'" | 拼接模糊匹配字符串(注意这里的 '%' 是字符串,需要加单引号) |
#{pattern} | MyBatis 会将 pattern 的值安全地替换进 SQL,防止 SQL 注入 |
📌 小技巧总结
目标 | 建议用法 |
---|---|
多条件查询 | <where> 或 <trim> 配合 <if> |
动态更新字段 | <set> 配合 <if> |
IN 查询 | <foreach> |
模糊搜索 | <bind> |
模拟 if…else | <choose> |
相关文章:
MyBatis 动态 SQL 使用详解
🌟 一、什么是动态 SQL? 动态 SQL 是指根据传入参数,动态拼接生成 SQL 语句,不需要写多个 SQL 方法。MyBatis 提供了 <if>、<choose>、<foreach>、<where> 等标签来实现这类操作 ✅ 二、动态 SQL 的优点…...
数据结构实验4.1:链队列的基本操作
文章目录 一,问题描述二,基本要求三,算法分析链队列的存储结构设计基本操作的算法分析 四,示例代码五,实验操作六,运行效果 一,问题描述 编程实现有关链队列的下列基本操作。 (1&am…...
独立部署及使用Ceph RBD块存储
Ceph RBD(RADOS Block Device) 是 Ceph 分布式存储系统中的块存储组件,类似于 AWS EBS、iSCSI 等。它独立于 OpenShift 或 IBM CP4BA,是一个分布式存储系统,提供高性能、可扩展性和容错能力,适用于数据库、…...
C++初阶-C++入门基础
目录 编辑 1.C的简介 1.1C的产生和发展 1.2C的参考文档 1.3C优势和难度 1.4C学习的建议 2.C的第一个程序 2.1打印Hello world 2.2头文件 2.3namespace命名空间 2.4::作用域限定符 2.5namespace的延伸 2.6C的输入输出 3.总结 1.C的简介 …...
部署大模型不再难:DeepSeek + 腾讯云 HAI 实战教程
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
算法训练之位运算
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
初识Linux:常见指令与权限的理解,以及相关衍生知识
目录 前言 关于linux的简介 代码开源 网络功能强大 系统工具链完整 一、Linux下的基本指令 1.ls指令 2.pwd指令 3.cd指令 4.whoami指令 5.touch指令 6.mkdir指令 7.rm指令 8.man指令 9.cp指令 10.mv指令 11.nano指令 12.cat指令 13.tac指令 14.more指令 15.less指令 16.head指令…...
PostgreSQL-数据库的索引 pg_operator_oid_index 损坏
报错信息: 连接测试失败 Error connecting to database: Connection failed: ERROR: index "pg_operator_oid_index" contains unexpected zero page at block 3 Hint: Please REINDEX it. 这个错误表明 PostgreSQL 数据库的索引 pg_operator_oid_index …...
数字图像处理作业4
数字图像处理 作业4 Project 4:Image Restoration The scoring method for this project is as follows: 1.Implement a blurring filter using the equation(5.6-11,数字图像处理(…...
Simulink中Signal Builder在新版中找不到怎么办
在较新的MATLAB版本中,新版Simulink中的Signal Builder用Signal Editor作为替代工具。 signal builder not shown in matlab - MATLAB Answers - MATLAB Central signalBuilderToSignalEditor 1.打开上面第二个链接 2.点击拷贝 3.然后在命令行中粘贴 4.然后就会…...
STM32——RTC实时时钟
RTC简介 RTC(Real Time Clock, RTC)实时时钟,其本质是一个计数器,计数频率常为秒,专门用来记录时间。 其具有能提供时间(秒钟数),能在MCU掉电后运行,低功耗的特性 内部框图 1. RTC预分频器 2. …...
sqli-labs靶场 less4
文章目录 sqli-labs靶场less 4 联合注入 sqli-labs靶场 每道题都从以下模板讲解,并且每个步骤都有图片,清晰明了,便于复盘。 sql注入的基本步骤 注入点注入类型 字符型:判断闭合方式 (‘、"、’、“”…...
指针数组 vs 数组指针
一、指针数组:「数组装指针」—— 每个元素都是指针 🔍 核心定义 语法:类型* 数组名[长度]; ([]优先级高于*,先形成数组,元素是指针)本质:一个 数组,数组的每个元素是 …...
GitHub优秀项目:数据湖的管理系统LakeFS
lakeFS 是一个开源工具,它将用户的对象存储转换为类似Git的存储库。使用户可以像管理代码一样管理数据湖。借助 lakeFS,可以构建可重复、原子化和版本化的数据湖操作--从复杂的ETL作业到数据科学和分析。 Stars 数11090Forks 数3157 主要特点 强大的数据…...
数据库视图讲解(view)
一、为什么需要视图 二、视图的讲解 三、总结 一、为什么需要视图 视图一方面可以帮我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询视图。 比如,针对一个公司的销售人员,我们只想给他看部分数据,…...
pip install pytrec_eval失败的解决方案
1、问题描述 在使用华为云 notebook 的时候,想要: !pip install transformer结果失败,阅读报错后,疑似是 pytrec_eval 库的下载问题。 于是,单独尝试: !pip install pytrec_eval发现确实是这个库安装失…...
使用stream的Collectors.toMap()方法常见问题
文章目录 一、常见问题二、key重复问题2.1、报错示例2.2、解决方法 三、value为空问题3.1、报错示例3.2、解决方法3.1、方案一3.2、方案二 一、常见问题 stream的Collectors.toMap()方法常见问题: 1、 key不能有重复,否则会报错。java.lang.IllegalStat…...
[C++面试] 初始化相关面试点深究
一、入门 1、C中基础类型的初始化方式有哪些?请举例说明 默认初始化 对于全局变量和静态变量,基础类型(如int、float、double等)会被初始化为 0;而对于局部变量,其值是未定义的,包含随机…...
ChatDBA:一个基于AI的智能数据库助手
今天给大家介绍一个基于 AI 大语言模型实现数据库故障诊断的智能助手:ChatDBA。 ChatDBA 是由上海爱可生信息技术股份有限公司开发,通过对话交互,提供数据库故障诊断、专业知识学习、SQL 生成和优化等功能,旨在提升 DBA 工作效率。…...
Java延迟队列
📌 1. 场景背景 最近做项目,使用到了延迟队列。场景是这样的:在在线视频学习中,学生每隔几秒上报当前学习进度,为避免频繁写数据库、提升性能,采用以下方案: 先写入 Redis,再延迟一…...
神舟平板电脑怎么样?平板电脑能当电脑用吗?
在如今的数码产品市场上,神舟平板电脑会拥有独特的优势,其中比较受到大家关注的就是神舟PCpad为例,无论是设计还是规格也会有很多的亮点,那么是不是可以直接当成电脑一起来使用呢? 这款平板电脑就会配备10.1英寸显示屏…...
Ansible的使用3
#### 一、Ansible补充模块 try () { } catch () { } finally 等同于 block () { } rescue () { } always ##### 任务块 - block任务块 - 通过block关键字,将多个任务组合到一起 - 将整个block任务组,一…...
PS教学记录
PS制作手机壁纸和电脑壁纸 1. 思绪来源 找到了一位B站UP,分享了有关于灰原哀的动态壁纸。自身( •̀ ω •́ )也是名侦探柯南的爱好者,在此基础上,萌生了制作壁纸的想法。便在B站上搜寻有关于壁纸制作的教学。找到了一位壁纸分享者的教程镜…...
分析一下HashMap内部是怎么实现的
当然可以!我们来深入分析一下 Java 中 HashMap 的内部实现机制(以 JDK 8 为主),包括数据结构、核心算法、源码设计、以及适用场景。 🧠 一、HashMap 的核心结构 HashMap 是基于哈希表实现的 Map,底层结构是…...
面向对象的要素
理解面向对象 程序的三种基本结构 (1)顺序结构 (2)选择结构 (3)循环结构 面向对象程序设计简介 面向对象是一种更优秀的程序设计方法,它的基本思想是使用类、对象、继承、封装、消息等基本…...
Java基础 4.9
1.方法递归调用练习 //请使用递归的方式求出斐波那契数1, 1, 2, 3, 5, 8, 13 //给你一个整数n, 求出它的值是多少 /* 思路 n 1 1 n 2 1 n > 3 前两个数的和 递归的思路 */ public class RecursionExercise01 {public static void main(String[] args) {Mathod mathod ne…...
什么是堆?深入理解堆数据结构及其应用
粉丝提问 ⭐算法OJ⭐数据流的中位数【最小堆】Find Median from Data Stream 发表后收到一位粉丝的私信询问: “经常听说堆、堆排序、优先队列这些概念,但一直不太明白堆到底是什么,能简单解释一下吗?它和内存分配中的堆是一回事…...
程序化广告行业(73/89):买卖双方需求痛点及应对策略深度剖析
程序化广告行业(73/89):买卖双方需求痛点及应对策略深度剖析 大家好!一直以来,我都热衷于在技术领域探索学习,也深知知识的分享能让我们共同进步。写这篇博客的目的,就是希望能和大家一起深入了…...
C++ RAII 的用途及业务代码实现案例
C RAII 的用途及业务代码实现案例 RAII 的核心概念 RAII (Resource Acquisition Is Initialization,资源获取即初始化) 是 C 的核心编程范式,其核心思想是: 资源获取与对象构造绑定资源释放与对象析构绑定利用 C 对象生命周期自动管理资源…...
神经网络入门—自定义神经网络续集
修改网络 神经网络入门—自定义网络-CSDN博客 修改数据集,yx^2 # 生成一些示例数据 x_train torch.tensor([[1.0], [2.0], [3.0], [4.0]], dtypetorch.float32) y_train torch.tensor([[1.0], [4.0], [9.0], [16.0]], dtypetorch.float32) 将预测代码改为&…...
【C语言】浮点数在内存的储存
前言: 在上章,了解了整数在内存中的储存,在本章节为大家继续讲解浮点数的储存,也是数据储存的最后一部分。 浮点数是计算机科学中一种重要的数据类型,用于表示实数。它能够表示非常大或非常小的数值,并且…...
安装 Calico 的两种主流方式对比
本文对比了 Calico 的两种主流安装方式: 使用 calico.yaml 的 Manifest 安装方式使用 Tigera Operator(tigera-operator.yaml custom-resources.yaml)安装方式 ✅ 1. 使用 Manifest 方式安装(直接部署 calico.yaml) …...
信用卡欺诈检测实战教程:从数据预处理到模型优化全解析
引言:为什么需要信用卡欺诈检测? 根据尼尔森报告,全球每年因信用卡欺诈造成的损失超过250亿美元,金融机构需要在0.1秒内完成交易风险评估。本文将带您从零构建基于机器学习的信用卡欺诈检测系统,完整代码可视化分析&a…...
android studio编译报错 Gradle
android studio 提示 Could not install Gradle distribution from https://services.gradle.org/distributions/gradle-8.0.2-bin.zip. Reason: java.net.SocketTimeoutException: Read timed out 一,手动下载 https://services.gradle.org/distributions/gradle…...
【Nodebb系列】Nodebb笔记写入方案
NodeBB写入方案 前言 最近在整理以前记录的碎片笔记,想把它们汇总到NodeBB中,方便管理和浏览。但是笔记内容有点多,并且用发帖的形式写到NodeBB中会丢失时间信息,因此整理了一套NodeBB写入方案,大致流程如下: 建立标准笔记格式导出原始笔记,并编写脚本将笔记内容转换为…...
Spring Boot 集成 POI
Spring Boot 集合 POI Apache POI 官站:https://poi.apache.org/ 基础概念 Apache POI 是一个开源项目,提供 Java API 用于操作 Microsoft Office 文件格式。Apache POI 对 Excel 文件的处理分为两个主要类库: HSSF (Horrible Spreadsheet …...
8个方向使用DeepSeek打磨完美课题申报书!
一份出色的课题申报书,往往就是项目获批的关键。撰写高质量课题申报书绝非易事,它需要您在选题切入点、研究价值论证、技术路线设计、团队优势呈现、经费规划和预期成果等多维度进行精心布局,确保论证有力、重点突出、结构清晰。 本文为您提供…...
Leetcode 34.在排序数组中查找元素的第一个和最后一个位置
题目描述 给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 考察二…...
ctfshow VIP题目限免 密码逻辑脆弱
根据题目提示:公开的信息比如邮箱,可能造成信息泄露,产生严重后果 在页面上找一个邮箱号 从 QQ 上面搜索这个 QQ号,发现是一个叫大牛的人,地区是陕西西安 然后我们拼接访问 /admin 发现了一个后台登录系统的页面&…...
C++初级入门学习
数据结构初级部分的学习我们已经学完了,接下来就进入C初阶部分的学习,因为数据结构的高阶部分要用到C才能够更好的理解并书写,所以我们要先学习C,初阶部分学完就能继续学习我们对数据结构了。好了,直接进入今天的主题吧…...
2025年汽车加气站操作工证考试内容
汽车加气站操作工证是从事汽车加气站相关操作工作的人员需要考取的资格证书 考试内容 理论知识:包括加气站的工艺流程、设备原理、安全操作规程、气体性质、消防知识、环境保护等方面的知识。例如,需要了解压缩天然气或液化天然气的储存、运输和加注流…...
python爬虫:喜马拉雅案例(破解sign值)
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关ÿ…...
嵌入式AI前沿:精选工具与应用网站解析
1. Edge Impulse 网址:https://www.edgeimpulse.com/核心内容: 提供端到端的嵌入式AI开发平台,简化从数据收集到模型训练再到部署的全流程。支持多模态数据处理(音频、视觉、运动等),并优化模型以在资源受…...
【论文精读】Multi-scale Neighbourhood Feature Interaction Network
摘要(ABSTRACT) 光伏发电是工业领域的关键组成部分,其能量转换效率受光伏电池表面缺陷的显著影响。近年来,深度学习模型的广泛应用推动了缺陷检测技术的进步。然而,由于光伏电池缺陷尺寸差异较大(尤其是微…...
C++ 蓝桥云课代码练习
代码一 ,小明的背包1,代码见下 #include <iostream> #include <cstring> using namespace std;#define maxn 110 #define maxm 1001 #define inf -1int w[maxn], v[maxn]; int dp[maxn][maxm];int main() {memset(dp, inf, sizeof(dp));dp[…...
微软庆祝它成立整整50周年
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
android 启动四大组件
在 Android 开发中,启动通常是指启动一个 Activity、Service、BroadcastReceiver 或其他组件。以下是一些常见的启动方式: 1. 启动一个 Activity 要启动一个 Activity,可以使用 Intent。以下是一个示例代码: 示例:启…...
C# 串口通信
1. 导入 using System.IO.Ports;2. 初始化定义 SerialPort sp new SerialPort(); // 设置串口 sp.PortName "COM3"; // 串口 sp.BaudRate 9600; // 波特率 sp.Parity Parity.None; // 校验位 sp.DataBits 8; // 数据位 sp.StopBits StopBits.One; // 停…...
Spring事务详解
一、Spring对事务的支持 1.事务概述 什么是事务 在一个业务流程当中,通常需要多条DML(insert delete update)语句共同联合才能完成,这多条DML语句必须同时成功,或者同时失败,这样才能保证数据的安全。 多…...
单片机FreeRTOSTickless低功耗模式应用示例
Tickless低功耗模式在很多需要延长电池寿命或减少能耗的场景中非常有用,特别是在那些大部分时间处于空闲状态的系统中。 以下是一些使用Tickless模式的场景和例子: 1.传感器节点在物联网(IoT)中,许多传感器节点需要长…...