当前位置: 首页 > news >正文

借助 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>

 

相关文章:

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

在上一篇的&#xff1a;Mybatis 操作数据库的基本 CRUD 以及查询操作详析_糊糊涂涂的博客-CSDN博客中介绍了Mybatis使用固定SQL语句操作数据&#xff0c;本篇介绍 Mybatis 一个强大的特性&#xff1a;动态SQL。 动态 SQL 解决什么问题&#xff1f; 那当我们要执行的业务逻辑有…...

前端框架学习-Vue(一)

Vue简介 百度百科上关于vue的词条&#xff0c;说vue时一款渐进式JavaScript框架&#xff0c; 简单来说,渐进式是一种设计理念,即在不失去当前功能的前提下,逐步添加新的特性。 说明它时一直在进行维护的。 Vue3&#xff0c;中使用*.vue作为文件后缀&#xff0c;html&#xff0c…...

Elasticsearch Query DSL

Elasticsearch Query DSL 这里使用的 Elasticsearch 的版本为 7.12.1。 1、基本概念 1.1 文档(Document) ElasticSearch 是面向文档的&#xff0c;文档是所有可搜索数据的最小单位&#xff0c;例如 MySQL 的一条数据记录。 文档会被序列化成为 json 格式&#xff0c;保存在…...

腾讯云 CODING × K+ 峰会再次携手开启软件行业新风向

点击链接了解详情 近日&#xff0c;K 全球软件研发行业创新峰会在北京成功举办。腾讯云 CODING 作为云原生工具领跑者受邀参与此次峰会。会议现场&#xff0c;展台打卡火爆、演讲干货满满&#xff0c;为观众带来高质量的行业内容。 腾讯云全链路高效 开发上云实践‍ 技术创新…...

2023年发布的25个开源大型语言模型总结

大型语言模型(llm)是一种人工智能(AI)&#xff0c;在大量文本和代码数据集上进行训练。它们可以用于各种任务&#xff0c;包括生成文本、翻译语言和编写不同类型的创意内容。 今年开始&#xff0c;人们对开源LLM越来越感兴趣。这些模型是在开源许可下发布的&#xff0c;这意味…...

Istio网关Gateway 启用TLS

Istio网关Gateway概述 Istio网关Gateway是一个负责处理南北向流量的组件&#xff0c;它通常会暴露服务网格内部的服务&#xff0c;以便外部的请求能够访问到服务网格中的服务。Istio网关Gateway支持多种协议&#xff0c;包括HTTP、HTTPS和GRPC等。 在Istio网关Gateway中&#…...

slam建图与定位_cartographer代码阅读(7)后端约束构建

1.cartographer里的节点:当扫描匹配结束后&#xff0c;有新的一帧scan加入到submap中&#xff0c;这个扫描匹配的结果就叫做节点 global_trajectory_builder.cc // 将匹配后的结果 当做节点 加入到位姿图中auto node_id pose_graph_->AddNode(matching_result->insertio…...

Android usb 配件模式通信示例

当使用 Android 设备作为 USB 配件时&#xff0c;可以使用 Android 提供的 USB Accessory API 来进行 USB 通信。以下是一个简单的 Android USB 配件模式的通信例子。在本例中&#xff0c;我们将接收连接到 Android 设备的 USB 主机发送的数据并向 USB 主机发送响应。 首先&am…...

【Hive实战】Hive的压缩池与锁

文章目录 Hive的压缩池池的分配策略自动分配手动分配隐式分配 池的等待超时Labeled worker pools 标记的工作线程&#xff08;自定义线程池&#xff09;Default pool 默认池Worker allocation 工作线程的分配 锁Turn Off ConcurrencyDebuggingConfigurationhive.support.concur…...

【VUE】使用elementUI tree组件根据所选id自动回显

需求如下&#xff1a; 1.点击父级节点 将父级节点下children中所有id放入数组 2.点击父级下的子节点 将点击的子节点放入数组 3.取消选择父节点&#xff0c;将放入数组的所有子节点id删除 4.根据选择的子节点数组&#xff0c;匹配他所属的父节点 <el-tree:data"tre…...

RocketMQ, Dashboard, 控制台安装

文章说明 本文主要说明RocketMQ的控制台&#xff08;Dashboard&#xff09;的安装过程。工作中一直用的是别人装好的&#xff0c;这次终于自己亲手装了一遍。 由于每次都要启动三个应用&#xff0c;比较烦&#xff0c;于是我写了一键启动脚本&#xff0c;分享给大家。这个脚本…...

chrome解决http自动跳转https问题

1.地址栏输入&#xff1a; chrome://net-internals/#hsts 2.找到底部Delete domain security policies一栏&#xff0c;输入想处理的域名&#xff0c;点击delete。 3.再次访问http域名不再自动跳转https了。...

FastGithub 下载

Releases dotnetcore/FastGithub GitHub 无需安装&#xff0c;双击UI程序即可运行。...

TSINGSEE青犀视频安防监控管理平台EasyNVR如何配置鉴权?

视频监控汇聚平台EasyNVR是基于RTSP/Onvif协议的视频平台&#xff0c;可支持将接入的视频流进行全平台、全终端的分发&#xff0c;分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。为了满足用户的集成与二次开发需求&#xff0c;我们也提供了丰富的API接口供…...

unittest 数据驱动DDT应用

前言 一般进行接口测试时&#xff0c;每个接口的传参都不止一种情况&#xff0c;一般会考虑正向、逆向等多种组合。所以在测试一个接口时通常会编写多条case&#xff0c;而这些case除了传参不同外&#xff0c;其实并没什么区别。 这个时候就可以利用ddt来管理测试数据&#xf…...

素数个数——数论

题目描述 求 1,2,⋯,N 中素数的个数。 输入格式 一行一个整数 N。 输出格式 一行一个整数&#xff0c;表示素数的个数。 样例 #1 样例输入 #1 10样例输出 #1 4提示 对于 100% 的数据&#xff0c;1≤1081≤N≤108。 本题时间限制在2秒以内。 因为题目时间限制是2秒&#xff0c;所…...

express编写一个简单的get接口

/01编写get接口.jsconst express require(express) const app express()// 创建路由 const useRouter require(./router/user.js) // 注册路由 app.use(/api,useRouter)app.listen(8080, (req, res) > {console.log(8080监听) }) ./02编写post接口 // 注意&#xff1a;如…...

【力扣刷题C++】环形链表

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/linked-list-cycle 著作权归领扣网络所有。商业转载请联系官方授权&#xff0c;非商业转载请注明出处。 【题目】给你一个链表的头节点 head &#xff0c;判断链表中是否有…...

如何用Python统计CSDN质量分

文章目录 CSDN质量分查询selenium爬取博客地址单篇测试批量查询分析 CSDN质量分查询 CSDN对博客有一套分数评价标准&#xff0c;其查询入口在这里&#xff1a;质量分查询&#xff0c;效果大致如下 如果质量分太低&#xff0c;就会在博文的标题下面出现黄底黄字&#xff1a; 这…...

gin框架内容(三)--中间件

gin框架内容&#xff08;三&#xff09;--中间件 Gin框架允许开发者在处理请求的过程中&#xff0c;加入用户自己的函数。这个函数就叫中间件&#xff0c;中间件适合处理一些公共的业务逻辑&#xff0c;比如登录认证、权限校验、数据分页、记录日志、耗时统计等 即比如&#x…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

(二)原型模式

原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...