动态 SQL

article/2025/8/22 11:05:25

文章目录

    • 一、学习目的
    • 二、动态 SQL 中的元素
    • 三、条件查询操作
    • 四、更新操作
    • 五、复杂查询操作
      • 1.foreach 元素中的属性
      • 2.foreach 元素迭代数组
      • 3.foreach 元素迭代 List
      • 4.foreach 元素迭代 Map

一、学习目的

在实际项目的开发中,开发人员在使用 JDBC 或其他持久层框架进行开发时,经常需要根据不同的条件拼接 SQL 语句,拼接 SQL 语句时还要确保不能遗漏必要的空格、标点符号等,这种编程方式给开发人员带来极大的不便,而 MyBatis 提供的 SQL 语句动态组装功能,恰能很好的解决这一问题,提高了 SQL 语句的复用性,本章将对 MyBatis 框架的动态 SQL 进行详细讲解。

二、动态 SQL 中的元素

在这里插入图片描述

三、条件查询操作

① if 元素

在 MyBatis 中,if 元素是最常用的判断元素,它类似于 Java 中的 if 语句,主要用于实现某些简单的条件判断。在实际应用中,我们可能会通过某个条件查询某个数据。例如,要查找某个客户的信息,可以通过姓名或者年龄来查找客户,也可以不填写年龄直接通过姓名来查找,还可以都不填写而查询出所有客户,此时姓名和年龄就是非必须条件。类似于这种情况的,我们都可以通过 if 元素来实现。

/*CustomerMapper.xml*/
<select id="findCustomer" parameterType="customer" resultType="customer">select * from customer where 1=1<if test="username!=null and username!=''">and username like concat('%',#{username},'%')</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></select>
//test.java
Customer customer = new Customer();
customer.setUsername("jack");
customer.setJobs("teacher");
List<Customer> customers = session.selectList("com.tyut.mapper.CustomerMapper.findCustomer",customer);
for (Customer c:customers) {System.out.println(c);
}
session.close();

为什么要使用 where 1=1?
第一个条件成立时,加不加 1=1 都是没有影响的,但是如果说我们的第一个语句中的条件并不成立,这时候肯定需要跳过它再去执行下一个语句,但是这时会报错,因为 where 后直接就跟了 and,这是不允许的,为了解决这个问题,我们使用 where 1=1。

当二者都为空时,查询到的结果则为整个表!

② choose、when 和 otherwise 元素

在使用 if 元素时,只要 test 属性中的表达式为 true,就会执行元素中的条件语句,但是在实际应用中,有时只需要从多个选项中选择一个去执行。例如,当客户名称不为空,则只根据客户名称进行客户筛选,与客户职业无关,当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选,当客户名称和客户职业都为空,则要求查询出所有电话不为空的客户信息。针对这种情况,使用 if 元素进行处理显然是不合理的,MyBatis 提供了 choose、when、otherwise 元素进行处理,这三个元素往往组合在一起使用,作用相当于 Java 语言中的 if…else。

/*CustomerMapper.xml*/
<select id="findCustomer" parameterType="customer" resultType="customer">select * from customer where 1=1<choose><when test="username!=null and username!=''">and username like concat('%',#{username},'%')</when><when test="jobs!=null and jobs!=''">and jobs=#{jobs}</when><otherwise>and phone is not null</othewrwise></choose>
</select>

if 元素不管后面有多少语句,只要条件为 true 则全部执行,而 choose 语句是从上到下找第一个条件为 true 的语句去执行,至于后面的各种语句一律不执行!

③ where 和 trim 元素

在映射文件中,编写的 SQL 语句后面加入了 “where 1=1” 的条件的话,既保证了 where 后面的条件成立,又避免了 where 后面第一个词是 and 或者 or 之类的关键字。其实除了 where 1=1 外,我们还可以使用 MyBatis 提供的 where 元素和 trim 元素解决这个问题。

/*CustomerMapper.xml*/
<select id="findCustomer" parameterType="customer" resultType="customer">select * from customer<where><if test="username!=null and username!=''">and username like concat('%',#{username},'%')</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></where>
</select>

where 元素会自动判断由组合条件拼装的 SQL 语句,只有 where 元素内的某一个或多个条件成立时,才会在拼装 SQL 中加入 where 关键字,否则将不会添加,即使 where 之后的内容有多余的 and 或 or,where 元素也会自动地将它们去除。

除了 where 外,trim 元素也可以用于删除多余的关键字,它可以直接实现 where 元素的功能,trim 元素包含四个属性。

在这里插入图片描述

/*CustomerMapper.xml*/
<select id="findCustomer" parameterType="customer" resultType="customer">select * from customer<trim prefix="where" prefixOverrides="and"><if test="username!=null and username!=''">and username like concat('%',#{username},'%')</if><if test="jobs!=null and jobs!=''">and jobs=#{jobs}</if></trim>
</select>

增加 where,剔除 and!

四、更新操作

实际应用中,大多数情况下我们都是只更新某一个或几个字段,如果更新的每一条数据都要将其所有的属性都更新一遍,那么执行效率是非常差的,为了解决更新数据的效率问题,MyBatis 提供了 set 元素,set 元素主要用于更新操作,它可以在动态 SQL 语句前输出一个 SET 关键字,并将 SQL 语句中最后一个多余的逗号去掉,set 元素与 if 元素结合可以实现只更新需要更新的字段。

/*CustomerMapper.xml*/
<update id="updateCustomerByset" parameterType="customer">update customer <set><if test="username!=null and username!=''">username=#{username},</if><if test="jobs!=null and jobs!=''">jobs=#{jobs},</if><if test="phone!=null and phone!=''">phone=#{phone},</if></set>where id=#{id}
</update>
//test.java
Customer customer = new Customer();
customer.setId(3);
customer.setPhone("85785785785");
int rows = session.update("com.tyut.mapper.CustomerMapper.updateCustomerById",customer);
if(rows>0) {System.out.println("修改了"+"rows"+"条数据!");
} else {System.out.println("数据修改失败!");
}
session.commit();
session.close();

① 在映射文件中使用 set 元素和 if 元素组合进行 update 语句动态 SQL 组装时,如果 set 元素内包含的内容都为空,则会出现 SQL 语法错误,因此,在使用 set 元素进行字段信息更新时,要确保传入的更新字段不能都为空;
② 除了使用 set 元素外,还可以通过 trim 元素来实现更新操作,其中 trim 元素的 prefix 属性指定要添加的 trim 元素所包含内容的前缀为 set,suffixOverrides 属性指定去除的 trim 元素所包含内容的后缀为逗号。

注意不要忘记 session.commit() 手动提交事务,否则我们对数据库所做的更改是不会永久性保存的!

五、复杂查询操作

1.foreach 元素中的属性

在这里插入图片描述

在遍历参数时,collection 属性的值是必须指定的,不同情况下,该属性的取值也是不一样的,主要有以下三种情况:

① 若遍历的参数是单个参数且参数类型是一个 List,collection 属性值为 list;
② 若遍历的参数是单个参数且参数类型是一个数组,collection 属性值为 array;
③ 若传入的参数为多个参数,就需要把参数封装为一个 Map 进行处理,collection 属性值为 Map。

2.foreach 元素迭代数组

例如要从数据表中查询出 id 为 1、2、3 的客户信息,就可以利用数组作为参数,存储 id 的属性值 1、2、3,并通过 foreach 元素迭代数组完成客户信息的批量查询操作。

/*CustomerMapper.xml*/
<select id="selectByArray" resultType="customer">select * from customer where id in<foreach collection="array" item="id" open="(" close=")" separator=",">#{id}</foreach>
</select>
//test.java
Integer[] ids = {2,3};
List<Customer> customers = session.selectList("com.tyut.mapper.CustomerMapper.selectByArray",ids);
for (Customer c:customers) {System.out.println(c);
}
session.close();

parameterType 属性可写可不写,所以完全可以不写!

3.foreach 元素迭代 List

/*CustomerMapper.xml*/
<select id="selectByList" resultType="customer">select * from customer where id in<foreach collection="list" item="id" open="(" close=")" separator=",">#{id}</foreach>
</select>
//test.java
List<Integer> ids = new ArrayList<>();
ids.add(2);
ids.add(3);
List<Customer> customers = session.selectList("com.tyut.mapper.CustomerMapper.selectByList",ids);
for (Customer c:customers) {System.out.println(c);
}
session.close();

4.foreach 元素迭代 Map

当 session 的 API 需要传入多个参数时,我们可以将多个参数封装到一个 Map 集合里面。

/*CustomerMapper.xml*/
<select id="selectByMap" resultType="customer">select * from customer where jobs=#{jobs} and id in<foreach collection="id" item="roleMap" open="(" close=")" separator=",">#{roleMap}</foreach>
</select>
//test.java
Map<String,Object> map = new HashMap<>();
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
map.put("id",ids);
map.put("jobs","teacher");
List<Customer> customers = session.selectList("com.tyut.mapper.CustomerMapper.selectByMap",map);
for (Customer c:customers) {System.out.println(c);
}
session.close();

Okey,到此为止我们的动态 SQL 就已讲解完毕,试着自己写一下学生信息查询系统,以便更好地巩固以上知识点。>_<


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

相关文章

第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 …

UFBGA176+25 封装尺寸图

下图是UFBGA17625 封装规格的参数&#xff0c;根据下图的参数&#xff0c;即可制作UFBGA17625 的PCB封装