当前位置: 首页 > article >正文

MyBatis 动态SQL 详解!

在这里插入图片描述

目录

    • 一、 什么是动态 SQL?
    • 二、 为什么需要动态 SQL?
    • 三、 MyBatis 动态 SQL 标签
    • 四、 标签详解及示例
      • 1、 if 标签
      • 2、 choose、when、otherwise 标签
      • 3、 where 标签
      • 4、 set 标签
      • 5、 foreach 标签
      • 6、 sql、include 标签
    • 五、 总结

🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方式,可以多多支持一下,感谢🤗!

🌟了解 MyBatis 结果映射 请看 : MyBatis 结果映射详解!

其他优质专栏: 【🎇SpringBoot】【🎉多线程】【🎨Redis】【✨设计模式专栏(已完结)】…等

如果喜欢作者的讲解方式,可以点赞收藏加关注,你的支持就是我的动力
✨更多文章请看个人主页: 码熔burning

这篇文章让我来好好讲解一下 MyBatis 的动态 SQL。

一、 什么是动态 SQL?

动态 SQL 是指在 SQL 语句中,根据不同的条件或参数,生成不同的 SQL 语句。 💡 在传统的 SQL 语句中,SQL 语句是固定的,无法根据不同的情况进行变化。 而动态 SQL 可以根据不同的条件,动态地拼接 SQL 语句,从而满足不同的查询需求。

MyBatis 提供了强大的动态 SQL 功能,允许你根据运行时条件构建 SQL 语句。这使得你可以编写更灵活、可维护的 SQL 映射。

二、 为什么需要动态 SQL?

  • 灵活性: 能够根据不同的条件生成不同的 SQL 语句,满足不同的查询需求。 🚀
  • 可维护性: 将 SQL 语句的逻辑与 Java 代码分离,使代码更易于维护。
  • 避免冗余: 避免编写大量的重复 SQL 语句,提高代码的复用性。
  • 性能优化: 可以根据不同的条件选择不同的索引,提高查询效率。 📈

三、 MyBatis 动态 SQL 标签

MyBatis 提供了一系列标签来构建动态 SQL。 以下是常用的标签及其用法:

  • <if>: 条件判断
  • <choose><when><otherwise>: 多条件选择
  • <where>: 智能 WHERE 子句
  • <set>: 智能 SET 子句
  • <foreach>: 循环遍历
  • <sql><include>: SQL 片段重用

四、 标签详解及示例

1、 if 标签

<if> 标签用于进行条件判断。 只有当 test 属性中的表达式为 true 时,才会将标签内的 SQL 片段添加到最终的 SQL 语句中。

<select id="findUsersByCondition" parameterType="map" resultType="User">SELECT * FROM usersWHERE 1=1 <!-- 避免第一个条件前出现 AND/OR --><if test="username != null and username != ''">AND username LIKE #{username}</if><if test="email != null and email != ''">AND email = #{email}</if>
</select>

解释:

  • id="findUsersByCondition":定义了一个名为 findUsersByCondition 的查询。
  • parameterType="map":指定参数类型为 map,这意味着你可以传递一个 Map 对象作为参数。
  • resultType="User":指定结果类型为 User 类。
  • WHERE 1=1:这是一个小技巧,用于避免在第一个条件前出现 ANDOR 关键字,导致 SQL 语法错误。 如果第一个 <if> 标签的条件成立,则会添加 AND 关键字,否则不会添加。
  • <if test="username != null and username != ''">:如果 username 不为 null 且不为空字符串,则添加 AND username LIKE #{username} 到 SQL 语句中。
  • <if test="email != null and email != ''">:如果 email 不为 null 且不为空字符串,则添加 AND email = #{email} 到 SQL 语句中。
  • #{username}#{email}:是 MyBatis 的参数占位符,用于将参数值安全地替换到 SQL 语句中。

Java 代码示例:

Map<String, Object> params = new HashMap<>();
params.put("username", "%john%");
params.put("email", "john.doe@example.com");List<User> users = sqlSession.selectList("findUsersByCondition", params);

生成的 SQL 语句示例:

如果 usernameemail 都不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE 1=1
AND username LIKE '%john%'
AND email = 'john.doe@example.com'

如果只有 username 不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE 1=1
AND username LIKE '%john%'

2、 choose、when、otherwise 标签

<choose> 标签类似于 Java 中的 switch 语句,用于多条件选择。 它包含多个 <when> 标签和一个 <otherwise> 标签。 MyBatis 会按照顺序评估每个 <when> 标签的 test 属性,如果有一个 <when> 标签的 test 属性为 true,则执行该 <when> 标签内的 SQL 片段,并跳过其他的 <when><otherwise> 标签。 如果所有的 <when> 标签的 test 属性都为 false,则执行 <otherwise> 标签内的 SQL 片段。

<select id="findUsersByCondition" parameterType="map" resultType="User">SELECT * FROM usersWHERE<choose><when test="username != null and username != ''">username LIKE #{username}</when><when test="email != null and email != ''">email = #{email}</when><otherwise>1=1 <!-- 如果没有条件,则查询所有用户 --></otherwise></choose>
</select>

解释:

  • <choose>:定义一个多条件选择结构。
  • <when test="username != null and username != ''">:如果 username 不为 null 且不为空字符串,则添加 username LIKE #{username} 到 SQL 语句中。
  • <when test="email != null and email != ''">:如果 email 不为 null 且不为空字符串,则添加 email = #{email} 到 SQL 语句中。
  • <otherwise>:如果 usernameemail 都为空,则添加 1=1 到 SQL 语句中,表示查询所有用户。

Java 代码示例:

Map<String, Object> params = new HashMap<>();
// params.put("username", "%john%"); // 只设置 username
// params.put("email", "john.doe@example.com"); // 只设置 emailList<User> users = sqlSession.selectList("findUsersByCondition", params);

生成的 SQL 语句示例:

如果 username 不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE
username LIKE '%john%'

如果 email 不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE
email = 'john.doe@example.com'

如果 usernameemail 都为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE
1=1

3、 where 标签

<where> 标签用于智能地添加 WHERE 子句。 它会自动判断是否需要添加 WHERE 关键字,并自动去除多余的 ANDOR 关键字。

<select id="findUsersByCondition" parameterType="map" resultType="User">SELECT * FROM users<where><if test="username != null and username != ''">username LIKE #{username}</if><if test="email != null and email != ''">AND email = #{email}</if></where>
</select>

解释:

  • <where>:智能地添加 WHERE 子句。
  • 如果至少有一个 <if> 标签的条件成立,则 <where> 标签会自动添加 WHERE 关键字,并去除第一个 AND 关键字。
  • 如果所有的 <if> 标签的条件都不成立,则 <where> 标签不会添加任何内容。

Java 代码示例:

Map<String, Object> params = new HashMap<>();
params.put("username", "%john%");
params.put("email", "john.doe@example.com");List<User> users = sqlSession.selectList("findUsersByCondition", params);

生成的 SQL 语句示例:

如果 usernameemail 都不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE username LIKE '%john%'
AND email = 'john.doe@example.com'

如果只有 username 不为空,则生成的 SQL 语句如下:

SELECT * FROM users
WHERE username LIKE '%john%'

如果 usernameemail 都为空,则生成的 SQL 语句如下:

SELECT * FROM users

4、 set 标签

<set> 标签用于智能地添加 SET 子句。 它会自动判断是否需要添加 SET 关键字,并自动去除最后一个逗号。 通常用于 UPDATE 语句中。

<update id="updateUser" parameterType="User">UPDATE users<set><if test="username != null and username != ''">username = #{username},</if><if test="email != null and email != ''">email = #{email},</if></set>WHERE id = #{id}
</update>

解释:

  • <set>:智能地添加 SET 子句。
  • 如果至少有一个 <if> 标签的条件成立,则 <set> 标签会自动添加 SET 关键字,并去除最后一个逗号。
  • 如果所有的 <if> 标签的条件都不成立,则 <set> 标签不会添加任何内容。

Java 代码示例:

User user = new User();
user.setId(1);
user.setUsername("new_username");
// user.setEmail("new_email@example.com"); // 不更新 emailsqlSession.update("updateUser", user);

生成的 SQL 语句示例:

如果 username 不为空,则生成的 SQL 语句如下:

UPDATE users
SET username = 'new_username'
WHERE id = 1

如果 usernameemail 都不为空,则生成的 SQL 语句如下:

UPDATE users
SET username = 'new_username',
email = 'new_email@example.com'
WHERE id = 1

5、 foreach 标签

<foreach> 标签用于循环遍历集合。 它可以用于构建 IN 子句、批量插入等场景。

<select id="findUsersByIds" parameterType="list" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="id" collection="list" open="(" separator="," close=")">#{id}</foreach>
</select>

解释:

  • item="id":指定集合中的每个元素的名字为 id
  • collection="list":指定要遍历的集合的名字为 list。 如果参数是数组,则 collection 属性的值为 array
  • open="(":指定循环开始时的字符串为 (
  • separator=",":指定每个元素之间的分隔符为 ,
  • close=")":指定循环结束时的字符串为 )
  • #{id}:表示集合中的每个元素的值。

Java 代码示例:

List<Integer> ids = Arrays.asList(1, 2, 3);List<User> users = sqlSession.selectList("findUsersByIds", ids);

生成的 SQL 语句示例:

SELECT * FROM users
WHERE id IN (1,2,3)

批量插入示例:

<insert id="insertUsers" parameterType="list">INSERT INTO users (username, email) VALUES<foreach item="user" collection="list" separator=",">(#{user.username}, #{user.email})</foreach>
</insert>

Java 代码示例:

List<User> users = new ArrayList<>();
users.add(new User("john", "john@example.com"));
users.add(new User("jane", "jane@example.com"));sqlSession.insert("insertUsers", users);

生成的 SQL 语句示例:

INSERT INTO users (username, email) VALUES
('john', 'john@example.com'),
('jane', 'jane@example.com')

6、 sql、include 标签

<sql> 标签用于定义 SQL 片段,<include> 标签用于引用 SQL 片段。 这可以提高代码的复用性。 ♻️

<sql id="userColumns">id, username, email
</sql><select id="findAllUsers" resultType="User">SELECT <include refid="userColumns"/> FROM users
</select><select id="findUserById" parameterType="int" resultType="User">SELECT <include refid="userColumns"/> FROM users WHERE id = #{id}
</select>

解释:

  • <sql id="userColumns">:定义一个名为 userColumns 的 SQL 片段,包含 id, username, email
  • <include refid="userColumns"/>:引用名为 userColumns 的 SQL 片段。

生成的 SQL 语句示例:

findAllUsers 生成的 SQL 语句:

SELECT id, username, email FROM users

findUserById 生成的 SQL 语句:

SELECT id, username, email FROM users WHERE id = 1

五、 总结

MyBatis 的动态 SQL 功能非常强大,可以根据不同的条件生成不同的 SQL 语句,从而满足不同的查询需求。 掌握这些标签的用法,可以编写更灵活、可维护的 SQL 映射。 🎉

一些建议:

  • 避免过度使用动态 SQL: 动态 SQL 虽然强大,但过度使用会增加代码的复杂性。 只有在必要的时候才使用动态 SQL。
  • 注意 SQL 注入: 在使用动态 SQL 时,要注意 SQL 注入的风险。 使用 MyBatis 的参数占位符 #{} 可以有效地防止 SQL 注入。
  • 测试: 编写充分的测试用例,确保动态 SQL 的正确性。 ✅

希望这篇文章能够帮助你理解 MyBatis 的动态 SQL。 😊

相关文章:

MyBatis 动态SQL 详解!

目录 一、 什么是动态 SQL&#xff1f;二、 为什么需要动态 SQL&#xff1f;三、 MyBatis 动态 SQL 标签四、 标签详解及示例1、 if 标签2、 choose、when、otherwise 标签3、 where 标签4、 set 标签5、 foreach 标签6、 sql、include 标签 五、 总结 &#x1f31f;我的其他文…...

本节课课堂总结

匿名子类&#xff1a; 说明 和 Java 一样&#xff0c;可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类。 单例对象&#xff08;伴生对象&#xff09; Scala语言是完全面向对象的语言&#xff0c;所以并没有静态的操作&#xff08;即在Scala中没有静态的概念&a…...

【Linux学习笔记】开发工具git和gbd和cgbd的介绍和使用

【Linux学习笔记】开发工具git和gbd和cgbd的介绍和使用 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 文章目录 【Linux学习笔记】开发工具git和gbd和cgbd的介绍和使用前言一. 版本控制器Git1.1版本控制器1.2 git 简史1.3 安…...

php的高速缓存

部署方法 在我们安装的nginx中默认不支持memc和srcache功能&#xff0c;需要借助第三方模块来让nginx支持此功能。 tar zxf srcache-nginx-module-0.33.tar.gz tar zxf memc-nginx-module-0.20.tar.gz 下载这俩个模块&#xff0c;然后编译安装的时候加进去 编译安装完成之后…...

Real-Time Anomaly Detection of Network Traffic Basedon CNN

1知识点补充 边缘计算模型 成为一种新的分布式数据处理方式&#xff0c;通过靠近数据侧&#xff0c;及时响应用户的计算请求&#xff0c;降低数据传输的网络延迟。 边缘节点是边缘计算架构中最基础的物理或逻辑单元&#xff0c;指位于网络边缘&#xff08;靠近数据源或用户&a…...

RHCSA LINUX系统文件管理

一.7种文件类型 注意&#xff1a;Linux系统文件名的后缀只是为了方便用户识别文件类型 Linux系统设计哲学&#xff1a;一切皆文件 1.使用 “ls -l” 命令查看到的第一个字符&#xff0c;对应不同文件类型及说明如下&#xff1a; ①“-”&#xff1a;普通文件&#xff0c;类…...

AQUA爱克泳池设备入驻济南校园,以品质筑牢游泳教育安全防线

在推进校园体育教育高质量发展的时代背景下&#xff0c;游泳作为一项兼具运动价值与生存技能的重要课程&#xff0c;正被越来越多的学校纳入教学体系。泳池作为开展游泳教学与运动的关键设施&#xff0c;其配套泳池设备的先进性与安全性愈发受到重视。作为泳池水处理设备行业的…...

基于CNN实现电力负荷多变量时序预测(PyTorch版)

前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记…...

网络空间安全(50)JavaScript基础语法

一、变量声明 ①var: 早期的变量声明方式&#xff0c;函数作用域。 ②let: 块级作用域&#xff0c;推荐在现代 JavaScript 中使用。 ③const: 块级作用域&#xff0c;用于声明常量&#xff0c;值不可变。 var name "Alice"; let age 30; const PI 3.14159; 二、数…...

深入理解二叉树、B树与B+树:原理、应用与实现

文章目录 引言一、二叉树&#xff1a;基础而强大的结构基本概念特性分析Java实现应用场景 二、B树&#xff1a;适合外存的多路平衡树基本概念关键特性查询流程示例Java简化实现典型应用 三、B树&#xff1a;数据库索引的首选核心改进优势分析范围查询示例Java简化实现实际应用 …...

【网络流 图论建模 最大权闭合子图】 [六省联考 2017] 寿司餐厅

题目描述&#xff1a; P3749 [六省联考 2017] 寿司餐厅 题目描述 Kiana 最近喜欢到一家非常美味的寿司餐厅用餐。 每天晚上&#xff0c;这家餐厅都会按顺序提供 n n n 种寿司&#xff0c;第 i i i 种寿司有一个代号 a i a_i ai​ 和美味度 d i , i d_{i, i} di,i​&…...

mysql对表,数据,索引的操作sql

对表的操作 新建表 创建一个名为rwh_test的表&#xff0c;id为主键自增 -- 新建表 CREATE TABLE rwh_test(id int NOT NULL auto_increment PRIMARY KEY COMMENT 主键id,username VARCHAR(20) DEFAULT NULL COMMENT 用户名,age int DEFAULT NULL COMMENT 年龄,create_date d…...

verl单机多卡与多机多卡使用经验总结

文章目录 I. 前言II. SFT2.1 单机多卡2.2 多机多卡 III. RL (GRPO)3.1 单机多卡3.2 多机多卡2.3 模型转换 I. 前言 在上一篇文章verl&#xff1a;一个集SFT与RL于一体的灵活大模型post-training框架 (快速入门) 中&#xff0c;初步探讨了verl框架的基础使用方法。在实际工业级…...

胶铁一体化产品介绍

•一体化结构特点介绍 胶框/铁框一体化技术最早在韩国采用&#xff0c;07年以来由于要求背光越做越薄。在采用0.4mm及以下厚度的LGP时&#xff0c;胶框及背光就会变得异常软,胶框不易组装&#xff0c;铁框松动等问题。 由于胶框和铁框是紧紧粘合在一起的&#xff0c;这正可以解…...

蓝桥杯刷题记录【并查集001】(2024)

主要内容&#xff1a;并查集 并查集 并查集的题目感觉大部分都是模板题&#xff0c;上板子&#xff01;&#xff01; class UnionFind:def __init__(self, n):self.pa list(range(n))self.size [1]*n self.cnt ndef find(self, x):if self.pa[x] ! x:self.pa[x] self.fi…...

基于BusyBox构建ISO镜像

1. 准备 CentOS 7.9 3.10.0-957.el7.x86_64VMware Workstation 建议&#xff1a;系统内核<3.10.0 使用busybox < 1.33.2版本 2. 安装busybox # 安装依赖 yum install syslinux xorriso kernel-devel kernel-headers glibc-static ncurses-devel -y# 下载 wget https://…...

Multisim14.3的安装步骤

Multisim14.3的安装步骤 安装包链接 右击Install.exe&#xff0c;以管理员身份运行 激活前关闭杀毒软件 右击&#xff0c;以管理员身份运行 依次右键【Base Edition】、【Full Edition】、【Power ProEdition】、【Full Edition】、【Power ProEdition】&#xff0c;选择【…...

搭建环境-opencv-qt

CMake Error at cmake/OpenCVCompilerOptimizations.cmake:647 (message): Compiler doesnt support baseline optimization flags: Call Stack (most recent call first): cmake/OpenCVCompilerOptions.cmake:344 (ocv_compiler_optimization_options) CMakeList 解决方…...

【愚公系列】《高效使用DeepSeek》050-外汇交易辅助

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

SparkAudio 是什么,和其他的同类 TTS 模型相比有什么优势

欢迎来到涛涛聊AI 在当今数字化时代&#xff0c;音频处理技术已经成为人们生活和工作中不可或缺的一部分。无论是制作有声读物、开发语音助手&#xff0c;还是进行影视配音&#xff0c;我们都离不开高效、精准的音频处理工具。然而&#xff0c;传统的音频处理技术往往存在诸多…...

jvm 的attach 和agent机制

Java 的 Attach 和 Agent 机制在实际应用中得到了广泛的成功应用&#xff0c;尤其是在监控、调试、性能分析、故障排查等方面。以下是这两种机制在实际场景中的一些成功应用案例&#xff1a; 1. 性能监控与分析 Java Agent 和 Attach 机制广泛应用于性能监控和分析&#xff0…...

Java 8 到 Java 21 系列之 Optional 类型:优雅地处理空值(Java 8)

Java 8 到 Java 21 系列之 Optional 类型&#xff1a;优雅地处理空值&#xff08;Java 8&#xff09; 系列目录 Java8 到 Java21 系列之 Lambda 表达式&#xff1a;函数式编程的开端&#xff08;Java 8&#xff09;Java 8 到 Java 21 系列之 Stream API&#xff1a;数据处理的…...

py文件打包为exe可执行文件,涉及mysql连接失败

py文件打包为exe可执行文件&#xff0c;涉及mysql连接失败 项目场景&#xff1a;使用flask框架封装算法接口&#xff0c;并使用pyinstaller打包为exe文件。使用pyinstaller打包多文件的场景&#xff0c;需要自己手动去.spec文件中添加其他文件&#xff0c;推荐使用auto-py-to-e…...

Ubuntu 系统 Docker 中搭建 CUDA cuDNN 开发环境

CUDA 是 NVIDIA 推出的并行计算平台和编程模型&#xff0c;利用 GPU 多核心架构加速计算任务&#xff0c;广泛应用于深度学习、科学计算等领域。cuDNN 是基于 CUDA 的深度神经网络加速库&#xff0c;为深度学习框架提供高效卷积、池化等操作的优化实现&#xff0c;提升模型训练…...

win10彻底让图标不显示在工具栏

关闭需要不显示的软件 打开 例此时我关闭了IDEA的显示 如果说只是隐藏&#xff0c;鼠标拖动一个道理 例QQ 如果说全部显示不隐藏...

Java服务端性能优化:从理论到实践的全面指南

目录 引言&#xff1a;性能优化的重要性 用户体验视角 性能优化的多维度 文章定位与价值 Java代码层性能优化方案 实例创建与管理优化 单例模式的合理应用 批量操作策略 并发编程优化 Future模式实现异步处理 线程池合理使用 I/O性能优化 NIO提升I/O性能 压缩传输…...

人脸识别和定位别的签到系统

1、功能 基于人脸识别及定位的宿舍考勤管理小程序 &#xff08;用户&#xff1a;宿舍公告、宿舍考勤查询、宿舍考勤&#xff08;人脸识别、gps 定 位&#xff09;、考勤排行、请假申请 、个人中心 管理员&#xff1a;宿舍管理、宿舍公告管理 学生信息管理、请假审批、发布宿舍…...

基于YOLOv8的热力图生成与可视化:支持自定义模型与置信度阈值的多维度分析

目标检测是计算机视觉领域的重要研究方向&#xff0c;而YOLO&#xff08;You Only Look Once&#xff09;系列算法因其高效性和准确性成为该领域的代表性方法。YOLOv8作为YOLO系列的最新版本&#xff0c;在目标检测任务中表现出色。然而&#xff0c;传统的目标检测结果通常以边…...

echarts+HTML 绘制3d地图,加载散点+散点点击事件

首先&#xff0c;确保了解如何本地引入ECharts库。 html 文件中引入本地 echarts.min.js 和 echarts-gl.min.js。 可以通过官网下载或npm安装&#xff0c;但这里直接下载JS文件更简单。需要引入 echarts.js 和 echarts-gl.js&#xff0c;因为3D地图需要GL模块。 接下来是HTM…...

Design Compiler:库特征分析(ALIB)

相关阅读 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 简介 在使用Design Compiler时&#xff0c;可以对目标逻辑库进行特征分析&#xff0c;并创建一个称为ALIB的伪库&#xff08;可以被认为是缓存&#xff09;&…...