四、MyBatis 动态语句

本章概要

  • 动态语句需求和简介
  • if 和 where 标签
  • set 标签
  • trim 标签(了解)
  • choose/when/otherwise 标签
  • foreach 标签
  • sql 片段

4.1 动态语句需求和简介

经常遇到很多按照很多查询条件进行查询的情况,比如智联招聘的职位搜索等。其中经常出现很多条件不取值的情况,在后台应该如何完成最终的SQL语句呢?

在这里插入图片描述

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

4.2 if 和 where 标签

使用动态 SQL 最常见情景是根据条件包含 where / if 子句的一部分。比如:

<!-- List<Employee> selectEmployeeByCondition(Employee employee); -->
<select id="selectEmployeeByCondition" resultType="employee">
  select emp_id,emp_name,emp_salary from t_emp
  <!-- where标签会自动去掉“标签体内前面多余的and/or” -->
  <where>
    <!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签判断的结果是否为true -->
    <!-- 在if标签的test属性中,可以访问实体类的属性,不可以访问数据库表的字段 -->
    <if test="empName != null">
      <!-- 在if标签内部,需要访问接口的参数时还是正常写#{} -->
      or emp_name=#{empName}
    </if>
    <if test="empSalary &gt; 2000">
      or emp_salary>#{empSalary}
    </if>
    <!--
    第一种情况:所有条件都满足 WHERE emp_name=? or emp_salary>?
    第二种情况:部分条件满足 WHERE emp_salary>?
    第三种情况:所有条件都不满足 没有where子句
    -->
  </where>
</select>

4.3 set 标签

<!-- void updateEmployeeDynamic(Employee employee) -->
<update id="updateEmployeeDynamic">
  update t_emp
  <!-- set emp_name=#{empName},emp_salary=#{empSalary} -->
  <!-- 使用set标签动态管理set子句,并且动态去掉两端多余的逗号 -->
  <set>
    <if test="empName != null">
      emp_name=#{empName},
    </if>
    <if test="empSalary &lt; 3000">
      emp_salary=#{empSalary},
    </if>
  </set>
  where emp_id=#{empId}
  <!--
  第一种情况:所有条件都满足 SET emp_name=?, emp_salary=?
  第二种情况:部分条件满足 SET emp_salary=?
  第三种情况:所有条件都不满足 update t_emp where emp_id=?
  没有set子句的update语句会导致SQL语法错误
  -->
</update>

4.4 trim 标签(了解)

使用 trim 标签控制条件部分两端是否包含某些字符

  • prefix属性:指定要动态添加的前缀
  • suffix属性:指定要动态添加的后缀
  • prefixOverrides属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
  • suffixOverrides属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值
<!-- List<Employee> selectEmployeeByConditionByTrim(Employee employee) -->
<select id="selectEmployeeByConditionByTrim" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id,emp_name,emp_age,emp_salary,emp_gender
  from t_emp

  <!-- prefix属性指定要动态添加的前缀 -->
  <!-- suffix属性指定要动态添加的后缀 -->
  <!-- prefixOverrides属性指定要动态去掉的前缀,使用“|”分隔有可能的多个值 -->
  <!-- suffixOverrides属性指定要动态去掉的后缀,使用“|”分隔有可能的多个值 -->
  <!-- 当前例子用where标签实现更简洁,但是trim标签更灵活,可以用在任何有需要的地方 -->
  <trim prefix="where" suffixOverrides="and|or">
    <if test="empName != null">
      emp_name=#{empName} and
    </if>
    <if test="empSalary &gt; 3000">
      emp_salary>#{empSalary} and
    </if>
    <if test="empAge &lt;= 20">
      emp_age=#{empAge} or
    </if>
    <if test="empGender=='male'">
      emp_gender=#{empGender}
    </if>
  </trim>
</select>

4.5 choose/when/otherwise 标签

在多个分支条件中,仅执行一个

  • 从上到下依次执行条件判断
  • 遇到的第一个满足条件的分支会被采纳
  • 被采纳分支后面的分支都将不被考虑
  • 如果所有的 when 分支都不满足,那么就执行 otherwise 分支
<!-- List<Employee> selectEmployeeByConditionByChoose(Employee employee) -->
<select id="selectEmployeeByConditionByChoose" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id,emp_name,emp_salary from t_emp
  where
  <choose>
    <when test="empName != null">emp_name=#{empName}</when>
    <when test="empSalary &lt; 3000">emp_salary &lt; 3000</when>
    <otherwise>1=1</otherwise>
  </choose>

  <!--
  第一种情况:第一个when满足条件 where emp_name=?
  第二种情况:第二个when满足条件 where emp_salary < 3000
  第三种情况:两个when都不满足 where 1=1 执行了otherwise
  -->
</select>

4.6 foreach 标签

基本用法,用批量插入举例

<!--
collection属性:要遍历的集合
item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符
open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
index属性:这里起一个名字,便于后面引用
遍历List集合,这里能够得到List集合的索引值
遍历Map集合,这里能够得到Map集合的key
-->
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
  <!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
  (#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>

批量更新时需要注意:
上面批量插入的例子本质上是一条SQL语句,而实现批量更新则需要多条SQL语句拼起来,用分号分开。也就是一次性发送多条SQL语句让数据库执行。此时需要在数据库连接信息的URL地址中设置:

atguigu.dev.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true

对应的foreach标签如下:

<!-- int updateEmployeeBatch(@Param("empList") List<Employee> empList) -->
<update id="updateEmployeeBatch">
  <foreach collection="empList" item="emp" separator=";">
    update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
  </foreach>
</update>

关于foreach标签的collection属性:
如果没有给接口中List类型的参数使用@Param注解指定一个具体的名字,那么在collection属性中默认可以使用collection或list来引用这个list集合。这一点可以通过异常信息看出来:
Parameter ‘empList’ not found. Available parameters are [arg0, collection, list]
在实际开发中,为了避免隐晦的表达造成一定的误会,建议使用@Param注解明确声明变量的名称,然后在foreach标签的collection属性中按照@Param注解指定的名称来引用传入的参数。

4.7 sql 片段

抽取重复的 SQL 片段

<!-- 使用sql标签抽取重复出现的SQL片段 -->
<sql id="mySelectSql">
  select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
</sql>

引用已抽取的 SQL 片段

<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】Linux进度条小程序(包含色块实现)

我们再将Linux常用工具与命令都学会了之后&#xff0c; 设计进度条这个小程序可以比较好的帮助我们进行一定程度练习与巩固 目录 预备知识&#xff1a;回车换行&#xff1a;缓冲区&#xff1a; 进度条&#xff1a;准备工作&#xff1a;主题思路&#xff1a;代码实现&#xff1a…

腾讯云服务器上发送邮件连接超时

腾讯云会将服务器25端口禁用&#xff08;腾讯云默认禁用&#xff09;&#xff0c;开启后发送正常 https://console.cloud.tencent.com/secctrl 参考 腾讯云服务器上发送邮件连接超时&#xff08;无法发送&#xff09;的相关问题

spring-boot-starter-validation常用注解

文章目录 一、使用二、常用注解三、Valid or Validated &#xff1f;四、分组校验1. 分组校验的基本概念2. 定义验证组3. 应用分组到模型4. 在控制器中使用分组5. 总结 一、使用 要使用这些注解&#xff0c;首先确保在你的 Spring Boot 应用的 pom.xml 文件中添加了 spring-bo…

使用EtherNET转Profinet网关配置EtherNET/IP地址说明

EtherNET转Profinet网关配置EtherNET/IP地址是将两种网络之间的连接进行设置和调整&#xff0c;以便实现数据的传输和信息的交互。这个过程中&#xff0c;需要对EtherNET/IP地址进行配置&#xff0c;以确保数据能够正确地在网络之间传递。通过配置EtherNET/IP地址&#xff0c;可…

vue2(Vuex)、vue3(Pinia)、react(Redux)状态管理

vue2状态管理Vuex Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它使用集中式存储管理应用的所有组件的状态&#xff0c;以及规则保证状态只能按照规定的方式进行修改。 State&#xff08;状态&#xff09;:Vuex 使用单一状态树&#xff0c;即一个对象包含全部的应用层…

sql管理工具archery简介

在平时的工作过程中&#xff0c;我们肯定会遇到使用sql平台的场景&#xff0c;业内也有很多工具&#xff0c;类似阿里云的dms&#xff0c;但是这个是和云厂商绑定的&#xff0c;我们可能一般没有用到阿里云组件就比较困难了&#xff0c;那还有什么选项了&#xff0c;经过调研&a…

JVM简介

一、什么是JVM JVM是Java Virtual Machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;JVM是一种用于计算设备的规范&#xff0c;它是一个虚构出来的计算机&#xff0c;是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java虚拟机包括一套字节码指令集、一组…

YOLOv5全网独家首发:Powerful-IoU更好、更快的收敛IoU,效果秒杀CIoU、GIoU等 | 2024年最新IoU

💡💡💡本文独家改进:Powerful-IoU更好、更快的收敛IoU,是一种结合了目标尺寸自适应惩罚因子和基于锚框质量的梯度调节函数的损失函数 💡💡💡MS COCO和PASCAL VOC数据集实现涨点 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_1251193…

哪些 3D 建模软件值得推荐?

云端地球是一款免费的在线实景三维建模软件&#xff0c;不需要复杂的技巧&#xff0c;只要需要手机&#xff0c;多拍几张照片&#xff0c;就可以得到完整的三维模型&#xff01; 无论是大场景倾斜摄影测量还是小场景、小物体建模&#xff0c;都可以通过云端地球将二维数据向三…

C++哈希表模拟实现unordered_map 与unordered_set

哈希概念 unordered系列的关联式容器&#xff08;如unordered_map unordered_set&#xff09; 之所以效率比较高&#xff0c;是因为其底层使用了哈希结构 顺序结构以及平衡树 中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff0c;因此在 查找一个元素 时&am…

php二次开发股票系统代码:腾讯股票数据接口地址、批量获取股票信息、转换为腾讯接口指定的股票格式

1、腾讯股票数据控制器 <?php namespace app\index\controller;use think\Model; use think\Db;const BASE_URL http://aaaaaa.aaaaa.com; //腾讯数据地址class TencentStocks extends Home { //里面具体的方法 }2、请求接口返回内容 function juhecurl($url, $params f…

Linux/Uinx 系统编程:进程管理(1)

Linux/Uinx 系统编程&#xff1a;进程管理&#xff08;1&#xff09; 文章目录 Linux/Uinx 系统编程&#xff1a;进程管理&#xff08;1&#xff09;什么是进程进程来源INIT 和 守护进程登录进程sh进程进程的执行模式进程管理的系统调用关于syscall中参数b&#xff0c;c&#x…

HCIP 三层交换

拓扑图&IP划分如下&#xff1a; 第一步&#xff0c;配置IP 以R1为例&#xff0c;R2同理 LSW1&#xff0c;LSW2同理 第二步&#xff0c;聚合链路 LSW1&#xff0c;LSW2同理 修改串口 LSW1&#xff0c;LSW2同理 第三步&#xff0c;配置生成树 LSW1&#xff0c;LSW2同理 …

听力下降为什么会影响到言语感知?

一、听力障碍对阈值、听觉频率范围和分辨能力的影响 听力障碍使得听障者的听敏度降低&#xff0c;提高了阈值&#xff0c;不利于言语信号的接收。听障者听力阈值的变化在不同频率并不相同&#xff0c;一般而言&#xff0c;高频部分的听力损失往往大于低频部分&#xff0c;而言…

代码随想录刷题笔记-Day11

1. 逆波兰表达式求值 150. 逆波兰表达式求值https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/ 给你一个字符串数组 tokens &#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意&a…

区块链技术在教育领域的应用:Web3教育变革

随着Web3时代的来临&#xff0c;区块链技术在各个领域都展现出了巨大的潜力&#xff0c;而在教育领域&#xff0c;区块链的应用正引领着一场教育变革。本文将深入探讨区块链技术在教育领域的创新应用&#xff0c;以及这一应用如何推动Web3时代的教育变革。 1. 学历和成绩的去中…

Shell脚本⑤函数与数组

一.函数 封装的可重复利用的具有特定功能的代码 格式&#xff1a; 方法一&#xff1a; [function] 函数名 (){ 命令序列 [return x] #使用return或者exit可以显式的结束函数 } 方法二&#xff1a; 函数名(){ 命令序列 } 1.函数的调用方法 &#xff08;1&…

【K8S 云原生】K8S的安全机制

目录 一、K8S安全机制概述 1、概念 2、请求apiserver资源的三个步骤&#xff1a; 一、认证&#xff1a;Anthentcation 1、认证的方式&#xff1a; 1、HTTP TOKEN&#xff1a; 2、http base&#xff1a; 3、http证书&#xff1a; 2、认证的访问类型&#xff1a; 3、签发…

【Power Platform】实现让审批人可以修改其他人提交的表单中的部分字段

之前我们分享的案例里&#xff0c;我提了一嘴我们的客户有一个需求&#xff0c;就是审批人要有能力修改其他人表单中的部分字段。 今天我们就来分享一下如何实现这个功能。 要实现这个效果&#xff0c;我们需要判断三个值——当前审批人是不是当前登录人、当前审批节点可以修…

基于python京东商品数据采集与可视化分析大屏设计与实现

随着电子商务行业的快速发展&#xff0c;京东作为中国最大的综合性电商平台之一&#xff0c;拥有海量的商品数据。对这些数据进行采集与分析&#xff0c;能够帮助企业了解市场趋势、消费者需求以及产品销售情况&#xff0c;为决策提供科学依据。 本文旨在基于京东商品数据的采…
最新文章