动态 SQL

news2025/7/18 8:32:43

文章目录

    • 一、学习目的
    • 二、动态 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://www.coloradmin.cn/o/5743.html

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

相关文章

【汇编 C++】多态底层---虚表、__vfptr指针

前言&#xff1a;如果对多态不太了解的话&#xff0c;可以看我的这篇文章《C多态》&#xff0c;另外本文中出现到的汇编代码&#xff0c;我都会予以解释&#xff0c;看不懂没关系&#xff0c;知道大概意思就行&#xff0c;能不讲汇编的地方我就不讲&#xff1b; 本文使用到的工…

networkx学习记录

networkx学习记录networkx学习记录1. 创建图表2. 节点3. 边4.检查图的元素5.从图中删除元素6.使用图构造函数7.访问边和邻居8.向图、节点和边添加属性9.有向图10. 绘制图形networkx学习记录 1. 创建图表 创建一个空图 import networkx as nx G nx.Graph()此时如果报以下错误…

HTML网页设计结课作业——11张精美网页 html+css+javascript+bootstarp

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 精彩专栏推荐&#x1f4…

学姐突然问我键盘怎么选?原来是为了这个...

前言&#xff1a; 上个星期学姐来问我该买啥键盘&#xff0c;说是自己用的笔记本的键盘实在是不太好用&#xff0c;很喜欢机械键盘的手感&#xff0c;但是常规的机械键盘有太大了而且声音十分大&#xff0c;对她们女生来说并不是很友好。于是我给她推荐了我现在正在用的这款键盘…

头歌-信息安全技术-Java生成验证码

头歌-信息安全技术-Java生成验证码一、第1关&#xff1a;使用Servlet生成验证码1、任务描述2、编程要求3、评测代码二、第2关&#xff1a;用户登录时校验验证码是否正确1、任务描述2、编程要求3、评测代码三、第3关&#xff1a;使用Kaptcha组件生成验证码1、任务描述2、编程要求…

2023年前端开发未来可期

☆ 对于很多质疑&#xff0c;很多不解&#xff0c;本文将从 △ 目前企业内前端开发职业的占比&#xff1b; △ 目前业内开发语言的受欢迎程度&#xff1b; △ 近期社区问答活跃度&#xff1b; 等维度来说明目前前端这个职业的所处位置。 ☆ 还有强硬的干货&#xff0c;通过深入…

跳槽前恶补面试题,成功上岸阿里,拿到33k的测开offer

不知不觉间&#xff0c;时间过得真快啊。作为一名程序员&#xff0c;应该都清楚每年的3、4月份和9、10月份都是跳槽的黄金季&#xff0c;各大企业在这段时间会大量招聘人才。在这段时间里&#xff0c;有人欢喜有人悲。想必各位在跳槽前都会做好充足的准备&#xff0c;同样做足了…

详细讲解网络协议:TCP和UDP什么区别?

该文章是学习了 B 站 up 主的视频做的总结&#xff0c;讲的很通俗易懂&#xff0c;首先感谢博主的分享。视频地址&#xff1a;https://www.bilibili.com/video/BV1kV411j7hA/?spm_id_from333.337.search-card.all.click&vd_source0a3d4c746a63d737330e738fa043eaf6 重新认…

【HDU No. 3567】八数码 II Eight II

【HDU No. 3567】八数码 II Eight II 杭电OJ 题目地址 【题意】 八数码&#xff0c;也叫作“九宫格”&#xff0c;来自一个古老的游戏。在这个游戏中&#xff0c;你将得到一个33的棋盘和8个方块。方块的编号为1&#xff5e;8&#xff0c;其中一块方块丢失&#xff0c;称之为“…

【python】基础复习

注&#xff1a;最后有面试挑战&#xff0c;看看自己掌握了吗 文章目录python的应用基础语法编码标识符python保留字第一个注释多行语句数字(Number)类型字符串(String)print 默认输出是换行的&#xff0c;如果要实现不换行需要在变量末尾加上 end""&#xff1a;impor…

猿创征文|在校大学生学习UI设计必备工具及日常生活中使用的软件

嗨&#xff0c;大家好&#xff0c;我是异星球的小怪同志 一个想法有点乱七八糟的小怪 如果觉得对你有帮助&#xff0c;请支持一波。 希望未来可以一起学习交流。 我是一名在校大二的学生&#xff0c;目前在学习关于UI设计方向的一些课程&#xff0c;平时会用到UI设计必备的工…

我终于读懂了适配器模式。。。

文章目录&#x1f5fe;&#x1f306;什么是适配器模式&#xff1f;&#x1f3ef;类适配器模式&#x1f3f0;对象适配器模式⛺️接口适配器模式&#x1f3ed;适配器模式在SpringMVC 框架应用的源码剖析&#x1f5fc;适配器模式的注意事项和细节&#x1f306;什么是适配器模式&am…

基于SDN环境下的DDoS异常攻击的检测与缓解--实验

基于SDN环境下的DDoS异常攻击的检测与缓解--实验基于SDN环境下的DDoS异常攻击的检测与缓解--实验1.安装floodlight2.安装sFlow-RT流量监控设备3.命令行安装curl工具4.构建拓扑5.DDoS 攻击检测6.DDoS 攻击防御7.总结申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&am…

PNG怎么转换成PDF?这篇文章教会你

有时候我们需要查找一些图片资料并将它打印出来&#xff0c;但是在网上的图片大多是以PNG格式存在的&#xff0c;这个时候&#xff0c;我们就需要先利用一些转换软件把PNG转换成PDF文件的格式&#xff0c;从而方便我们进行打印。那么你们知道PNG转PDF怎么转换吗&#xff1f;今天…

第四章:前缀和、差分(数列)

前缀和差分一、前缀和1、 什么是前缀和2、 前缀和的作用3、 前缀和的例题和模板&#xff08;1&#xff09;一维数组的前缀和C版C版&#xff08;2&#xff09;二维数组的前缀和a.思路&#xff1a;b.题目和模板&#xff1a;C版C版二、差分1、什么是差分&#xff1f;2、差分有什么…

FFplay文档解读-43-视频过滤器十八

29.170 telecine 将电视电影处理应用于视频。 此过滤器接受以下选项&#xff1a; first_field选项解释top, ttop field firstbottom, b底部字段优先默认值为top pattern一串数字&#xff0c;表示希望应用的下拉模式。 默认值为23。 Some typical patterns:NTSC output (30i…

传统纸业如何实现数字化,S2B2C系统网站赋能渠道提升供应链管理效率

一千多年前&#xff0c;我们老祖宗发明了造纸术&#xff0c;纸张成为方便、廉价的信息载体&#xff0c;由此影响了中国乃至世界文明的进程。如今&#xff0c;随着信息技术的普及&#xff0c;纸张作为信息载体的功能日益弱化&#xff0c;但作为一种环保材料将会更广泛地融入我们…

通过宠物商店理解java面向对象

前言&#xff1a;本篇博客&#xff0c;适合刚刚学完java基础语法的但是&#xff0c;对于面向对象&#xff0c;理解不够深刻的读者&#xff0c;本文通过经典的宠物商店&#xff0c;来让读者深刻的理解&#xff0c;面向对象&#xff0c;IS-A&#xff0c;HAS-A法则。本文不仅仅是简…

Spring更简单保存和获取bean对象的方法(注解)

Spring更简单保存和获取bean对象的方法前置准备将bean对象更为简单地保存到Spring容器中&#xff08;使用注解&#xff09;【使用类注解】 (是写在类前的)为什么要这么多类注解&#xff1f;类注解之间的关系使用类注解 Bean 命名规则使用方法注解&#xff08;Bean&#xff09;不…

[MySQL]数据库的约束与表的设计

专栏简介 :MySql数据库从入门到进阶. 题目来源:leetcode,牛客,剑指offer. 创作目标:记录学习MySql学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 文章目录 1.数据库约束 1.1 约束类型 1.2 null 约束 1.…