动态SQL

article/2025/8/21 18:38:48

动态SQL

在项目开发中,动态SQL可以解决很多不确定因素导致的SQL语句不同的问题。动态SQL可以简单高效的进行编码。在接下来的案例中进行认识和学习动态SQL。
动态SQL只是在原有的SQL语句中进行细微修改。案例贴合实际,编码简单易懂

文章目录

  • 动态SQL
    • 一、引入动态SQL
    • 二、 接口方法的参数定义
    • 三、动态SQL标签元素
      • 3.1 不确定多条件查询—— if、where 标签
      • 3.2 不确定单个条件查询——choose (when, otherwise) 标签
      • 3.3 修改数据——set、if 标签
      • 3.4 批量删除——foreach 标签

一、引入动态SQL

如下图片中的功能:
在这里插入图片描述
我们经常会遇到如上图所示的多条件查询,将多条件查询的结果展示在下方的数据列表中。而我们做这个功能需要分析最终的SQL语句应该是什么样,思考两个问题

  • 条件表达式
  • 如何连接

条件字段 企业名称 和 品牌名称* 需要进行模糊查询,所以条件应该是:

在这里插入图片描述

简单的分析后,我们来看功能实现的步骤:
编写接口方法
参数:所有查询条件
结果:List
在映射配置文件中编写SQL语句

二、 接口方法的参数定义

在 BrandMapper 接口中定义多条件查询的方法。而该功能有三个参数,我们就需要考虑定义接口时,参数应该如何定义。Mybatis针对多参数有多种实现

1.使用 @Param(“参数名称”) 标记每一个参数,在映射配置文件中就需要使用 #{参数名称} 进行占位

List<Brand> selectByCondition(@Param("status") int status, @Param("companyName") String companyName,@Param("brandName") String brandName);

2.将多个参数封装成一个 实体对象 ,将该实体对象作为接口的方法参数。该方式要求在映射配置文件的SQL中使用 #{内容} 时,里面的内容必须和实体类属性名保持一致。

List<Brand> selectByCondition(Brand brand);

3.将多个参数封装到map集合中,将map集合作为接口的方法参数。该方式要求在映射配置文件的SQL中使用#{内容}时,里面的内容必须和map集合中键的名称一致。

List<Brand> selectByCondition(Map map);

编写SQL语句,在 BrandMapper.xml 映射配置文件中编写 SQL语句 ,使用 resultMap 而不是使用 resultType

<select id="selectByCondition" resultMap="brandResultMap">select * from tb_brandwhere status = #{status}and company_name like #{companyName}and brand_name like #{brandName}
</select>

问题分析:
上述功能实现存在很大的问题。用户在输入条件时,肯定不会所有的条件都填写,这个时候我们的SQL语句就不能那样写的。如下:

  • 用户只输入 当前状态 时,SQL语句就是
select * from tb_brand where status = #{status}
  • 而用户如果只输入企业名称时,SQL语句就是
select * from tb_brand where company_name like #{companName}
  • 而用户如果输入了 当前状态 和 企业名称 时,SQL语句又不一样
select * from tb_brand where status = #{status} and company_name like #{companName}

三、动态SQL标签元素

针对上述的需要,Mybatis对动态SQL有很强大的支撑——动态SQL的标签元素:

if
choose (when, otherwise)
where
set
foreach
trim

在接下来的四个案例中进行学习动态SQl标签的用法

3.1 不确定多条件查询—— if、where 标签

对于以上案例,进行的解决方案: 在 BrandMapper.xml 映射配置文件中编写条件查询数据的SQl语句:

<select id="selectByCondition" resultMap="brandResultMap">select *from tb_brand<where><if test="status != null">and status = #{status}</if><if test="companyName != null and companyName != '' ">and company_name like "%"#{companyName}"%"</if><if test="brandName != null and brandName != '' ">and brand_name like "%"#{brandName}"%"</if></where>
</select>
  • if 标签:条件判断
    • test 属性:逻辑表达式
  • where 标签
    • 作用:
      1. 替换where关键字
      2. 会动态的去掉第一个条件前的 and
      3. 如果所有的参数没有值则不加where关键字
      4. 注意:需要给每个条件前都加上 and 关键字。

3.2 不确定单个条件查询——choose (when, otherwise) 标签


如上图所示,在查询时只能选择 品牌名称 、 当前状态 、 企业名称 这三个条件中的一个,但是用户到底选择哪儿一个,我们并不能确定。这种就属于单个条件的动态SQL语句。
这种需求需要使用到 choose(when,otherwise)标签实现, 而 choose 标签类似于Java 中的switch语句。

针对于上述案例的解决方法:在 BrandMapper 接口中定义单条件查询的方法:

/*** 单条件动态查询* @param brand* @return*/
List<Brand> selectByConditionSingle(Brand brand);

在 BrandMapper.xml 映射配置文件中编写 SQL,使用 resultMap 而不是使用 resultType

<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brand<where><choose><!--相当于switch--><when test="status != null"><!--相当于case-->status = #{status}</when><when test="companyName != null and companyName != '' "><!--相当于case-->company_name like #{companyName}</when><when test="brandName != null and brandName != ''"><!--相当于case-->brand_name like #{brandName}</when></choose></where>
</select>

3.3 修改数据——set、if 标签

在 BrandMapper.xml 映射配置文件中编写修改数据的SQl语句:

<update id="update">update tb_brand<set><if test="brandName != null and brandName != ''">brand_name = #{brandName},</if><if test="companyName != null and companyName != ''">company_name = #{companyName},</if><if test="ordered != null">ordered = #{ordered},</if><if test="description != null and description != ''">description = #{description},</if><if test="status != null">status = #{status}</if></set>where id = #{id};
</update>

set 标签可以用于动态包含需要更新的列,忽略其它不更新的列。

3.4 批量删除——foreach 标签

在 BrandMapper 接口中定义删除多行数据的方法:

/*** 批量删除*/
void deleteByIds(int[] ids);

在 BrandMapper.xml 映射配置文件中编写批量删除的SQl语句:

<delete id="deleteByIds">delete from tb_brand where idin<foreach collection="array" item="id" separator="," open="(" close=")">#{id}</foreach>;
</delete>

假如数组中的id数据是{1,2,3},那么拼接后的sql语句就是:

delete from tb_brand where id in (1,2,3);
  • foreach 标签:用来迭代任何可迭代的对象(如数组,集合)。
属性含义
collectionmybatis会将数组参数,封装为一个Map集合。默认:array = 数组;使用@Param注解改变map集合的默认key的名称
item本次迭代获取到的元素
separator集合项迭代之间的分隔符。 foreach 标签不会错误地添加多余的分隔符。也就是最后一次迭代不会加分隔符。
open该属性值是在拼接SQL语句之前拼接的语句,只会拼接一次
close该属性值是在拼接SQL语句拼接后拼接的语句,只会拼接一次

小贴士: 上述动态SQL中的标签元素最为常用,但并不只有这些。理解这些标签的含义,在实际的功能中:具体情况具体分析,灵活编码。有些标签是可以嵌套使用的。


http://chatgpt.dhexx.cn/article/hDujVLUt.shtml

相关文章

动态 SQL

文章目录 一、学习目的二、动态 SQL 中的元素三、条件查询操作四、更新操作五、复杂查询操作1.foreach 元素中的属性2.foreach 元素迭代数组3.foreach 元素迭代 List4.foreach 元素迭代 Map 一、学习目的 在实际项目的开发中&#xff0c;开发人员在使用 JDBC 或其他持久层框架…

第3章 动态SQL

目录/Contents 第3章 动态SQL学习目标掌握MyBatis中动态SQL元素的使用掌握MyBatis的条件查询操作掌握MyBatis的更新操作掌握MyBatis的复杂查询操作 学习内容1 动态SQL中的元素1.1 使用动态SQL的好处1.2 动态SQL常用元素 2 条件查询操作2.1 \<if>元素2.2 \<choose>、…

Mybatis的特性详解——动态SQL

Mybatis的特性详解——动态SQL 前言一、动态sql的元素1.MyBatis if标签&#xff1a;条件判断2.MyBatis choose、when和otherwise标签3.MyBatis where标签4.MyBatis set标签5.MyBatis foreach标签6.MyBatis bind标签7.MyBatis trim标签仰天大笑出门去&#xff0c;我辈岂是蓬蒿人…

Java编程基础八股文(背诵版)

Java语言具有哪些特点&#xff1f; Java为纯面向对象的语言。它能够直接反应现实生活中的对象。 具有平台无关性。java利用Java虚拟机运行字节码&#xff0c;无论是在Windows、Linux还是MacOS等其它平台对Java程序进行编译&#xff0c;编译后的程序可在其它平台运行。 Java为…

Java编程基础篇

目录 计算机、程序和Java概述计算机组成 基本程序设计标识符数值数据类型格式化控制台输出输入输出重定向输入重定向输出重定向输入输出重定向方法重载变量的范围 数组声明数组变量创建数组初始化数组可边长参数二维数组静态变量、常量和方法静态变量 限定字符串StringBuilder和…

Java 基础编程入门

一、什么是Java Java是一种编程语言二、应用场景 非windows平台下互联网环境的开发首选三、Java语言特点 1、应用面广 2、简单易学(相对于C/C) 3、面向对象(更符合我们看待事物的特点) 4、跨平台(一处编译&#xff0c;处处运行) 5、多线程(提升系统性能) 单线…

JAVA的编程基础(上)

1. JAVA的基本语法 1.1 注释 单行注释&#xff1a;// 多行注释&#xff1a;/* */ 文档注释&#xff1a;/** */ 注意&#xff1a;单行注释可以嵌套&#xff0c;多行注释和文档注释不可以嵌套 1.2 关键字 含义&#xff1a;在编程语言中&#xff0c;已经被赋予一些特殊含义…

Java编程基础(1)

1.Java基本语法 &#xff08;1&#xff09;Java程序的基本格式&#xff1a; 修饰符 class 类名 { 程序代码 } 如果Java程序要运行&#xff0c;则必须要有main方法&#xff0c;main方法是程序运行的入口 格式&#xff1a; 修饰符 class 类名{ public static void main&…

Java编程基础之网络编程

网络编程 文章目录 网络编程概述C/S和B/S网络通信协议网络编程要素 IP类UDP协议数据传输发送端接收端udp数据传输丢失问题 TCP概述Socket客户端ServerSocket服务端Socket**服务器代码**客户端代码 文件上传实现客户端服务端多线程版 概述 C/S和B/S 网络通信协议 协议:protoco…

java编程基础(一)二进制

文章目录 二进制面试题bit 和 bytejava 中的 byte 类型java 中 byte 类型表示正数&#xff1a;java 中 byte 类型表示负数&#xff1a; 四种整数类型的最小和最大值二进制和十进制的互转练一练java 代码中直接写二进制字面值代码仓库 二进制 对于任何已知类型的传统计算机而言…

Java 基础

Java 基础知识点整理 Java 语言是一种优秀的编程语言&#xff0c;由 C 语言、C 语言发展而来。Java 语言提供了一些有效的新特性&#xff0c;使得使用 Java 比 C 更容易写出“无错代码”。 Java特性和优点 面向对象编程的思想&#xff0c;更简单有效&#xff0c;Java 省略了 …

Java编程基础②

Java编程基础 Java中的注释Java中的标识符Java中的关键字Java中的常量常量类型定义常量 java中的变量变量的定义及其数据类型变量的类型转换变量的作用域 java运算符算术运算符赋值运算符比较运算符逻辑运算符位运算符运算符的优先级 java流程控制语句if条件语句switch条件语句…

第二章 Java编程基础

第二章 Java编程基础 目录 一&#xff0e; Java基本语法1. 基本格式2. 注释3. 标识符4. 关键字5. 常量 二&#xff0e; 变量1. 定义2. 数据类型3. 整数类型变量4. 浮点类型变量5. 字符类型变量6. 布尔类型变量7. 类型转换8. 自动提升9. 变量作用域 三&#xff0e; 运算符1. 算数…

【JAVA】1.编程基础

1.Java基本语法 JAVA基本格式&#xff1a; 修饰符 class 类名{ 程序代码 } public class java {public static void main(String[] args) {System.out.println("HelloWorld"); } public static void main(String[] args) {} &#xff08;对于初学者来说这个部分必…

第二章Java编程基础

一、填空题 1&#xff0e;Java程序代码必须放在一个类中&#xff0c;类使用class关键词定义。 2&#xff0e;Java中的注释有三类&#xff0c;分别是单行注释、多行注释、文档注释。 3&#xff0e;Java语言中&#xff0c;int类型所占存储空间为4个字节。 4&#xff0e;用于比…

Java基础 —— 编程入门

一、比特(bit)和字节(byte) 一个0或者一个1存储为一个比特(bit)&#xff0c;是计算机中最小的存储单位。计算机中是最基本的存储单元是字节(byte)。 每个字节由8个比特构成。 计算机就是一系列的电路开关。每个开关存在两种状态:关(off)和开(on)。如果电路是开的&#xff0c;它…

第二章:JAVA编程基础

目录 一&#xff1a;Java的基本语法格式 二&#xff1a;Java中的变量与常量 三&#xff1a;Java中的运算符 四&#xff1a;选择结构语句 五&#xff1a;循环结构语句 六&#xff1a;数组 一&#xff1a;Java的基本语法格式 1&#xff1a;语法格式 [修饰符] class 类名{…

Java编程基础知识(一)

目录 一.Java的基本语法 1.Java的基本语法格式 2.Java中的注释 3.Java中的关键字 Java中的标识符 二.Java中的常量与变量 1.常量 2.变量 三.Java中的运算符 四.数据输入 一.Java的基本语法 1.Java的基本语法格式 编写Java程序必须先声明一个类&#xff0c;然后再类中…

Java编程基础

目录 第一篇、Java编程基础 ❀Java中的属性名词 ❀Java数据类型 ❀转义字符 ❀&& 和 & 与 || 和 | ❀方法 第二篇、Java面向对象编程 ❀类和对象 ❀面向过程和面向对象的区别 ❀面向对象程序设计的主要特性 ❀类和对象概述 ❀对象的内存结构 ❀垃圾空间…

java编程基础(入门级)(超级完整版)

java基础编程&#xff08;入门&#xff09; 01基础知识 1.计算机基础 【1】进制 A.十进制转化二进制 除以2&#xff0c;求余数&#xff0c;商继续除以2&#xff0c;一直到0为止&#xff0c;从底下往上得到结果。 B.二进制转化十进制 1 | 1 | 0 | 0 2 3 ∣ 2 2 ∣ 2 1 ∣ 2 …