借助 Mybatis 的动态 SQL 解决传参不确定问题


在上一篇的:Mybatis 操作数据库的基本 CRUD 以及查询操作详析_@糊糊涂涂的博客-CSDN博客中介绍了Mybatis使用固定SQL语句操作数据,本篇介绍 Mybatis 一个强大的特性:动态SQL。

动态 SQL 解决什么问题?

        那当我们要执行的业务逻辑有很多,比如给成绩表中插入一行数据,对应学生的 “性别” 字段是非必须参数时,使用动态SQL就不用写两种插入语句(传与不传性别);

        另外,当执行查询逻辑时,条件中的参数个数也是不确定的。

        以上类似传入参数不确定的情况,都可以使用动态SQL来解决。


1. <if> 标签:

         <if>标签可以用来判断参数是否符合预期值,从而决定 SQL 语句的拼接;

        下面假设要给 student 表插入一行数据,学生的 sex 字段对应的实体类中 sex 属性值为null,借助<if>标签判断是否要在插入时插入 sex :

Maper 接口: 

@Mapper
public interface StudentMapper {// 新增学生信息int addStu(Student student);
}

 插入语句:

<mapper namespace="com.example.demo.mapper.StudentMapper"><insert id="addStu">insert into student (uid, name<if test="sex != null and sex != '' ">,sex</if>,score) values (#{uid}, #{name}<if test="sex != null and sex != '' ">,#{sex}</if>,#{score})</insert>
</mapper>

 测试方法:

@SpringBootTest
class StudentMapperTest {@Autowiredprivate StudentMapper studentMapper;@Transactional@Testvoid addStu() {Student student = new Student();student.setUid(1);student.setName("张三");student.setScore(98);// 传入的实体对象中不包含 sexint result = studentMapper.addStu(student);System.out.println("插入成功:" + result);}
}

!!!使用时要注意区分属性和字段:

test 里要判断的是“属性” —— 来自实体类对象;

其他的是字段 —— 和数据库对应;


2. <trim> 标签:

        <trim>标签还会结合<if>标签一起使用,它有字面意思“修剪”的含义。

        当SQL语句中有很多个非必传参数时,一旦只传其中个别参数,就会导致残留逗号或括号等情况,导致SQL语句出现错误;<trim> 标签就会根据实际情况,去掉残留不必要的内容。

<trim>标签的四个参数:

        可根据场景添加

  • prefix:表示整个语句块,以prefix的值作为前缀
  • suffix:表示整个语句块,以suffix的值作为后缀
  • prefixOverrides:表示整个语句块要去除掉的前缀
  • suffixOverrides:表示整个语句块要去除掉的后缀

下面演示:插入一条学生信息,但参数只传学生名,就会导致字段后面多出一个逗号,同时如果不穿参数,又会多出一对括号,借助 trim 来修改:

Mapper 接口: 

@Mapper
public interface StudentMapper {// 只插入学生姓名int addStuOnlyName(Student student);
}

SQL 语句:

    <insert id="addStuOnlyName">insert into student<trim prefix="(" suffix=")" suffixOverrides=","><if test="uid != null and uid != '' ">uid,</if><if test="name != null and name != '' ">name,</if><if test="sex != null and sex != '' ">sex,</if><if test="score != null and score != '' ">score</if></trim>values<trim prefix="(" suffix=")" suffixOverrides=","><if test="uid != null and uid != '' ">#{uid},</if><if test="name != null and name != '' ">#{name},</if><if test="sex != null and sex != '' ">#{sex},</if><if test="score != null and score != '' ">#{score}</if></trim></insert>

单元测试:

@Testvoid addStuOnlyName() {Student student = new Student();student.setName("李四");int result = studentMapper.addStuOnlyName(student);System.out.println("插入成功:" + result);}

 


3. <where> 标签:

        直接借助示例演示:根据学生 uid 或 学生名 来查询一条学生信息,这里的两个查询条件都是非必传的。

        ① 如果查询时只给了其中一个条件,那么 where 后面连接时的 "and" 就会被多出来;

        ② 如果两个条件都不穿,那么 "where" 就会被多出来;

针对第一种情况:可以使用<trim> 标签去后缀的方式去掉 and,and 放在参数的后面;

针对第二种情况:解决办法很多种:

  1. where 后添加 1=1,and 放在每个条件参数前面,使用<trim>去前缀去掉and;
            (但这种写法很冗余,不是好办法)

  2. where 作为<trim>标签的前缀,只有<trim>里有代码,才会自动加上前缀 where,再按照去后缀的方式去掉 and;

  3. 使用 <where> 标签,专门解决这种场景:
        <where> 里面有内容,就会自动生成 where,没有就不生成。
    ​​​​​​​​​​​​​​   同时:如果有多出来的 and ,它也会
    按照去前缀的方式去掉

            

 


4. <set> 标签:

        <set> 标签用于修改场景,<set>标签也是包着所有参数,如果没有内容,就不加 set,但没有set语句对于 mysql 是错误的,所以至少要传一个参数

        <set> 会自动去掉多余的逗号

    <update id="updateStu">update student<set><if test="uid != null and uid > 0">uid = #{uid},</if><if test="name != null and name != '' ">name = #{name},</if><if test="sex != null and sex != '' ">sex = #{sex},</if><if test="score != null and score > 0">score = #{score}</if></set>where uid = #{uid}</update>

5. <foreach> 标签:

        <foreach> 标签用于遍历传入的集合,它有五个可选项:

  1. collection:绑定方法参数中的集合,如 List,Set,Map或数组对象
  2. item:遍历时的每⼀个对象
  3. open:语句块开头的字符串
  4. close:语句块结束的字符串
  5. separator:每次遍历的对象之间间隔的字符串
    // 根据 uid 批量删除int deleteByUids(List<Integer> uidList);
    <delete id="deleteByUids">delete from studentwhere uid in<foreach collection="uidList" item="uid" open="(" close=")" separator=",">#{uid}</foreach></delete>

 

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

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

相关文章

【Nodejs】Node.js开发环境安装

1.版本介绍 在命令窗口中输入 node -v 可以查看版本 0.x 完全不技术 ES64.x 部分支持 ES6 特性5.x 部分支持ES6特性&#xff08;比4.x多些&#xff09;&#xff0c;属于过渡产品&#xff0c;现在来说应该没有什么理由去用这个了6.x 支持98%的 ES6 特性8.x 支持 ES6 特性 2.No…

vue3如何封装接口

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;如何封装接口 目录 前言 1.首先&#xff0c;安装并导入axios库。你可以使用npm或yarn来安装&#xff1a; 2.创建一个api.js文件来管理接口封装&#xff1a; 3.在Vue组件中使用封装的接口&#xff1…

安装Python之后 安装库报错 There was an error checking the latest version of pip.

报错代码 & 图片如下 Looking in indexes: https://pypi.tuna.tsicmdnghua.edu.cn/simple WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection broken by NewConnectionError(<pip._vendor.urllib3.connection.HT…

Ubuntu 曝Linux漏洞,近 40% 用户受影响

Bleeping Computer 网站披露&#xff0c;Wiz 研究人员 s.Tzadik 和 s.Tamari 发现 Ubuntu 内核中存在两个 Linux 漏洞 CVE-2023-32629 和 CVE-2023-2640&#xff0c;没有特权的本地用户可能利用其在设备上获得更高权限&#xff0c;影响大约 40% 的 Ubuntu 用户。 Ubuntu 是目前…

双重for循环优化

项目中有段代码逻辑是个双重for循环&#xff0c;发现数据量大的时候&#xff0c;直接导致数据接口响应超时&#xff0c;这里记录下不断优化的过程&#xff0c;算是抛砖引玉吧~ Talk is cheap,show me your code&#xff01; 双重for循环优化 1、数据准备2、原始双重for循环3、…

【设计模式——学习笔记】23种设计模式——组合模式Composite(原理讲解+应用场景介绍+案例介绍+Java代码实现)

案例引入 学校院系展示 编写程序展示一个学校院系结构: 需求是这样&#xff0c;要在一个页面中展示出学校的院系组成&#xff0c;一个学校有多个学院&#xff0c;一个学院有多个系 【传统方式】 将学院看做是学校的子类&#xff0c;系是学院的子类&#xff0c;小的组织继承大…

K8s使用Ceph作为后端存储

Ceph概述 部署Ceph集群 Ceph存储使用 Pod使用Ceph持久化数据 Ceph监控 Rook部署Ceph 1❖ Ceph概述 Ceph介绍 Ceph架构 Ceph核心概念 Ceph介绍 Ceph是一个开源的分布式存储系统&#xff0c;具有高扩展性、高性能、高可靠性等特点&#xff0c;提 供良好的性能、可靠性和可扩展…

ROS与STM32通信-rosserial

文章目录 硬件接线 软件STM32CubeMX配置 rosserial移植上位机订阅-下位机发布上位机订阅下位机发布通信 上位机发布-下位机订阅上位机发布下位机订阅通信 硬件 STM32F103c8t6OLED(I2C)USB2TTLStlink 接线 OLED(GPIO模拟I2C) 硬件引脚OLEDSCLPA4OLEDSDAPA5 USART1 硬件引脚…

CSS3 Flexbox

Flex 是 Flexible Box 的缩写&#xff0c;意为弹性盒子布局。 CSS3中一种新的布局模式&#xff1a;W3C在2009年提出的一种布局方案&#xff0c;一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。其目的是提供一种更加有效的方式来对一个容器…

深度学习入门(二):神经网络整体架构

一、前向传播 作用于每一层的输入&#xff0c;通过逐层计算得到输出结果 二、反向传播 作用于网络输出&#xff0c;通过计算梯度由深到浅更新网络参数 三、整体架构 层次结构&#xff1a;逐层变换数据 神经元&#xff1a;数据量、矩阵大小&#xff08;代表输入特征的数量…

打造完美直播体验:美颜技术与美型SDK的融合

随着直播行业的蓬勃发展&#xff0c;主播们对于直播体验的要求也日益提高。其中&#xff0c;美颜技术和美型SDK的融合为主播们带来了前所未有的完美直播体验。本文将深入探讨美颜技术和美型SDK的原理与应用&#xff0c;以及这两者如何协同工作&#xff0c;为直播行业带来更具吸…

Clion开发stm32之微妙延迟(采用nop指令实现)

前言 需要借助逻辑分析仪动态调整参数此次测试的开发芯片为stm32f103vet6 延迟函数 声明 #define NOP_US_DELAY_MUL_CNT 5 /*nop 微妙延迟需要扩大的倍数(根据实际动态修改)*/ void bsp_us_delay_nop(uint32_t us);void bsp_ms_delay_nop(uint32_t ms);定义 void bsp_us_dela…

【QT 网络云盘客户端】——获取用户文件列表信息

目录 1.获取用户文件列表信息分析 2.设置图标属性 3.向服务器获取文件的数量 4.向服务器获取文件信息列表 4.显示图标 1.获取用户文件列表信息分析 1.将QListWidget设置为图标模式 2. 当我们点击"按下载量升序","按下载量降序",“更新” 菜单选项 都会…

【SQL Server】DBCC CHECKDB只是一个数据库维护命令吗?

日期&#xff1a;2023年7月27日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

JVM简述

JDK&JRE&JVMJVM运行时内存结构图方法区堆区栈区程序计数器本地方法栈 JVM 的主要组成部分及其作用 JDK&JRE&JVM JVM就是java虚拟机&#xff0c;一台虚拟的机器&#xff0c;用来运行java代码 但并不是只有这台机器就可以的&#xff0c;java程序在运行时需要依赖…

sql查询语句大全-详细讲解(格式、示例)

目录 范围查询 BETWEEN...AND in 为空 模糊查询 去重查询 AND OR 排序查询 聚合函数 1.count&#xff1a;计算个数 2.max&#xff1a;计算最大值 3.min&#xff1a;计算最小值 4.sum&#xff1a;计算和 5.avg&#xff1a;计算平均数 分组查询 group by 分组后…

观察者模式、中介者模式和发布订阅模式

观察者模式 定义 观察者模式定义了对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都将得到通知&#xff0c;并自动更新 观察者模式属于行为型模式&#xff0c;行为型模式关注的是对象之间的通讯&#xff0c;观察者模式…

Pytorch(一)

目录 一、基本操作 二、自动求导机制 三、线性回归DEMO 3.1模型的读取与保存 3.2利用GPU训练时 四、常见的Tensor形式 五、Hub模块 一、基本操作 操作代码如下: import torch import numpy as np#创建一个矩阵 x1 torch.empty(5,3)# 随机值 x2 torch.rand(5,3)# 初始化…

NoSQL之Redis配置使用

目录 一、关系数据库与非关系型数据库 1.1.关系型数据库的概述 1.2关系型数据库的优缺点 1.2.1优点 1.2.2缺点 1.3.非关系型数据库的概述 二.关系数据库与非关系型数据库的区别 2.1数据存储方式不同 2.2扩展方式不同 2.3对事务性的支持不同 2.4非关系型数据库产生背景 2…

浅析嵌入式GUI框架-LVGL

LVGL是什么&#xff1f; LVGL (Light and Versatile Graphics Library) 是最流行的免费开源嵌入式图形库&#xff0c;可为任何 MCU、MPU 和显示类型创建漂亮的 UI。 嵌入式GUI框架对比 Features/框架LVGLFlutter-elinuxArkUI(鸿蒙OS)AWTKQTMIniGUIemWinuC/GUI柿饼UI跨平台…