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="ANDOR "> … `
<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>

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

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

相关文章

乐观锁与悲观锁的使用场景

悲观锁的应用场景 悲观锁的基本思想是假设并发冲突会发生&#xff0c;因此在操作数据时会先锁定数据&#xff0c;直到完成操作并提交事务后才释放锁。这种方式适用于写操作较多、并发冲突可能性较高的场景。 高写入比例的数据库操作&#xff1a;如果系统中有很多写操作&#x…

cpp(c++)win 10编译GDAL、PROJ、SQLite3、curl、libtiff

cpp&#xff08;c&#xff09;编译GDAL、PROJ、SQLite3 Sqlite3libtiffcurlprojGDAL Sqlite3 1、下载 Sqlite3 源码、工具、二进制预编译 exe Sqlite3 官网&#xff1a;https://www.sqlite.org/download.html 下载 sqlite-amalgamation-3430200.zipsqlite-dll-win64-x64-3430…

【愚公系列】《高效使用DeepSeek》062-图书库存管理

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…

链表算法中常用操作和技巧

目 1.常用技巧 1.1.画图 1.2.添加虚拟头节点 1.3.大胆引入中间变量 1.4.快慢双指针 1.4.1判断链表是否有环 1.4.2找链表中环的入口 ​2.常用操作 2.1. 创建一个新节点 2.2.尾插 2.3.头插 1.常用技巧 1.1.画图 画图可以让一些抽象的文字语言更加形象生动 画图&#…

【9】数据结构的串篇章

目录标题 串的定义顺序串的实现初始化赋值打印串求串的长度复制串判断两个串长度是否相等连接两个串比较两个串内容是否相等插入操作删除操作调试与代码合集 串的模式匹配算法朴素的模式匹配算法KMP算法实现模式匹配 串的定义 定义&#xff1a;由0个或多个字符组成的有限序列&…

GMSL Strapping Pins CFG0/CFG1 应用

GMSL device 使用起来还是比较简单 ADI 已经充分考虑了用户的需求&#xff0c;尽可能的降低的芯片的使用和配置复杂度 一对加串器和解串器&#xff0c;只要工作模式匹配得当&#xff0c;Link Locked&#xff0c;便能够正常工作 如果遇到 Link 无法建立&#xff08;Locked&…

`uia.WindowControl` 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式

uia.WindowControl 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式 uia.WindowControl 通常是基于 Windows 系统的 UI 自动化框架(如 pywinauto 中的 uia 模块)里用于表示窗口控件的类。在 Windows 操作系统中,每个应用程序的窗口都可以看作是一个控件,ui…

Easysearch VS Opensearch 数据写入与存储性能对比

本文记录 Easysearch 和 Opensearch 数据写入和数据存储方面的性能对比。 准备 压测工具&#xff1a;INFINI Loadgen 对比版本&#xff1a; Easysearch 1.11.1&#xff08;lucene 8.11.4&#xff09;Opensearch 2.19.1&#xff08;lucene 9.12.1&#xff09; 节点 JVM 配置…

力扣题解:142. 环形链表 II

在链表学习中&#xff0c;我们已经了解了单链表和双链表&#xff0c;两者的最后一个结点都会指向NULL&#xff1b;今天我们介绍的循环列表则不同&#xff0c;其末尾结点指向的这是链表中的一个结点。 循环链表是一种特殊类型的链表&#xff0c;其尾节点的指针指向头节点&#…

区间 dp 系列 题解

1.洛谷 P4342 IOI1998 Polygon 我的博客 2.洛谷 P4290 HAOI2008 玩具取名 题意 某人有一套玩具&#xff0c;并想法给玩具命名。首先他选择 W, I, N, G 四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好&#xff0c;将名字中任意一个字母用 W, I, N, G …

天基光学图像仿真原理简介

一、原理简介 天基光学图像仿真通过数学模型和算法模拟空间目标在光学系统中的成像过程&#xff0c;核心原理可归纳为以下四部分&#xff1a; 1. 目标与背景建模‌ 目标运动建模‌&#xff1a;利用轨道动力学模型&#xff08;如SGP4&#xff09;解析空间目标轨迹&#xff0c;…

Jetpack Compose 状态保存机制全面解析:让UI状态持久化

在Android开发中&#xff0c;Jetpack Compose 的状态管理是一个核心话题&#xff0c;而状态保存则是确保良好用户体验的关键。本文将深入探讨Compose中各种状态保存技术&#xff0c;帮助你在配置变更和进程重建时保持UI状态。 一、基础保存&#xff1a;rememberSaveable reme…

【Json-Rpc #1】项目背景及环境搭建

&#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人博客&#xff1a;island ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; 生活总是不会一帆风顺&#xff0c;前进…

WPF轮播图动画交互 动画缩放展示图片

WPF轮播图动画交互 动画缩放展示图片 效果如下图&#xff1a; XAML代码&#xff1a; <Window x:Class"Caroursel.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/20…

为什么 npm list -g 没显示 node_modules?✨

揭秘&#xff1a;为什么 npm list -g 没显示 node_modules&#xff1f;&#x1f575;️‍♂️✨ 嗨&#xff0c;各位代码探险家&#xff01;&#x1f44b; 今天我们要破解一个 npm 小谜团&#xff1a;运行 npm list -g --depth0 时&#xff0c;为什么输出的路径里看不到 node_…

都江堰与郑国渠

目录标题 一、历史背景&#xff1a;地缘博弈下的水利突围都江堰&#xff1a;化水患为天府的千年大计郑国渠&#xff1a;间谍引发的战略反转 二、工程智慧&#xff1a;超越时代的科技奇迹都江堰&#xff1a;生态治水的典范郑国渠&#xff1a;泥沙资源化的创举 三、后世影响&…

链路聚合+vrrp

1.链路聚合 作用注意事项将多个物理接口&#xff08;线路&#xff09;逻辑上绑定在一起形成一条逻辑链路&#xff0c;起到叠加带宽的作用1.聚合接口必须转发速率一致。2.聚合设备两端必须一致 配置命令 方法一 [Huawei]interface Eth-Trunk 0----先创建聚合接口&#xff0c;…

【STM32单片机】#7 定时器输入捕获

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…

【android bluetooth 框架分析 01】【关键线程 3】【bt_jni_thread 线程介绍】

1. bt_jni_thread 职责介绍 bt_jni_thread 这个线程的作用是专门负责处理蓝牙 JNI 层的消息循环&#xff0c;也可以说是 C 层和 Java 层交互的桥梁线程。 1.1 什么是 JNI 层&#xff1f;为什么需要这个线程&#xff1f; JNI&#xff08;Java Native Interface&#xff09;是 …

基于视觉语言模型的机器人实时探索系统!ClipRover:移动机器人零样本视觉语言探索和目标发现

作者&#xff1a;Yuxuan Zhang 1 ^{1} 1, Adnan Abdullah 2 ^{2} 2, Sanjeev J. Koppal 3 ^{3} 3, and Md Jahidul Islam 4 ^{4} 4单位&#xff1a; 2 , 4 ^{2,4} 2,4佛罗里达大学电气与计算机工程系RoboPI实验室&#xff0c; 1 , 3 ^{1,3} 1,3佛罗里达大学电气与计算机工程系F…