MyBatis 动态SQL的标签有哪些?如何使用?

目录

1. MyBatis 动态SQL标签有什么用?

2. if 标签

3. where 标签

4. trim 标签

5. choose,when,otherwise

6. foreach


1. MyBatis 动态SQL标签有什么用?

我来说一个场景大家就明白了,如下图,大家应该在铁路12306上买过火车票吧,可以看到,我们在选票的时候可以对车做很多种选择和筛选,系统会自动根据你的选择给你匹配适应的车次,其实它的底层就是采用的动态SQL拼接的方式完成的,系统会根据用户不同的选择动态生成不同的SQL语句,然后交给数据访问层去操作查询。

 下面我就来一个个介绍MyBatis框架给我们提供了哪些动态 SQL 拼接的标签。

2. if 标签

当我们实际开发多条件查询让用户选择的业务场景时,也许用户不会把所有筛选条件都选上,比如我们出去旅游,在美团上订酒店,可以按距离,按价格,按星级筛选,也许你不会把所有条件都选上,可能只选一个,但它也会查询出结果,这个时候它就可以采用 if 标签生成动态SQL语句达到我们的目的。

if 标签可以通过它提供的 test 属性对数据内容做判断,判断是否满足要求。若满足,if 标签内部的内容就会执行,反之则不执行。

使用方式就是

<if test = "判断条件">为true要执行的语句段<if>

示例如下代码所示

// 在 mapper 映射文件中写我们的 SELECT 查询语句
// 这里if标签内不能使用Java中的 && 连接符,mybatis 为我们提供了and关键字专门用来做连接操作
<select id="findByNameAndAge" resultType="User">
            select * from user where 1=1
            <if test="username != null and username != ''">
                and username = #{username}
            </if>
            <if test="age != null and age != ''">
                and age = #{age}
            </if>
        </select>
// 这里我只是写了 username 和 age 连个字段,实际开发过程中字段也许会很多,
// 这里举例就写的简单一些,其实都一样,当有其他字段时,继续追加 if 标签就可以了

如上举例 if 标签,我们可以在开发时,就可以将用户不一定选择的查询条件使用 if 标签包裹起来,test = "" 双引号内部就是我们的判断条件,不为空或者不为空字符串,和我们Java中的 if 判断非常相似,只有我们的 test 判断结果为 true,即用户输入的结果不为空也不是空字符串,说明用户输入的是有效数据,我们就将用户想要查询的过滤条件加入到查询条件中,如果为false,则该字段的筛选条件不参与SQL语句中。

这里有几个注意点我要提醒一下,各位同学千万注意!!!

(1)在 where 条件的后面,我们最好写一个恒成立的等式,例如1=1,2=2;

(2)每个 if 标签内的字段前面都要加上一个 and;

因为如果我们 if 标签内的结果都不成立,那么 SQL 语句就变成了 SELECT * FROM user WHERE 1=1。语法没有任何问题,但如果我们不加1=1 ,查询语句就会变成 SELECT * FROM user WHERR。WHERE 查询条件后面没有任何东西,就会出现语法级别的错误,这是绝对不允许出现的,为了避片此种情况,我们可以在 WHERE后面加上一个恒成立条件,使 WHERE 关键字无论何时都会起作用并且 SQL 语句语法不出错;

这是其中一点,另外一点就是,可以和我们 if 标签内的 and 完美连接。

我举一个例子,假设前端传递过来的数据 username 为空不满足条件,那么 SQL 语句就变成了 SELECT * FROM user WHERE 1=1 and age = #{age}。此时语法也没有任何问题,并且可以和 and 关键字巧妙连接。不但解决了可能出现的 SQL 语法问题,还解决了 and 关键字可能多余的情况。

3. where 标签

WHERE 标签的使用方式也很简单,大多是搭配 if 使用的。

使用方式 <WHERE>if 表标签内容</WHERE>

可以看到,在我刚才 if 标签中,我们将WHERE关键字写死了,不管后面的 if 标签是否生效,WHERE都会拼接到SQL语句中,这样的写法有些死板,而我们的 WHERE 标签就可以动态生成 WHERE 关键字。

将刚才 if 中的代码修改后如下:

<select id="findByNameAndAge" resultType="User">
            select * from user
            <where>
                <if test="username != null and username != ''">
                    username = #{username}
                </if>
                <if test="age != null and age != ''">
                    and age = #{age}
                </if>
            </where>
        </select>

我们只需要将所有的条件判断全部写到 WHERE 标签内部即可。

(1)WHERE标签内只要有一个条件生效,WHERE就会动态生成并拼接到SQL语句中;

(2)如果WHERE标签内部的都不执行,那么WHERE也不会生成;

(3)WHERE 还可以智能地将语句前面多余的 and 删除,也可以将 or 删除。

(4)and 或 or 连接符只能写在字段判断的前面,不能写在后面,否则 WHERE 标签将无法自动智能删除,只有写在前面才有效果;

例如,我的 username =#{username}不执行,那么理论上SQL语句就会变成 SELECT * FROM user WHERE and age = #{age}。但实际上,WHERE标签会智能将 and 删除,就会变成 SELECT * FROM user WHERE age = #{age}。

4. trim 标签

trim 标签是一个单独的标签,它可以单独使用,如下图,可以看到,该标签一共提供了四个属性

其中 prefix 翻译过来是"前缀",prefixOverrides 为 "前缀重写",suffix 为 "后缀",suffixOverrides 为 "后缀重写"。

prtefix/suffix:在trim标签中内容前面/后面添加指定内容;

prefixOverrides/suffixOverrides:在trim标签中内容前面/后面去掉指定内容;

而且 trim 标签中有内容时,trim就会生效,如果没有内容,trim标签也不会生效。

我们想要达到上面 WHERE 标签一样的效果,可以像下面这样写,使用 prefix 属性添加前缀 WHERE,使用 prefixOverrides 去掉多余的 and和or,他们中间用 "|" 连接。

<select id="findByNameAndAge" resultType="User">
            select * from user
            <trim prefix="where" prefixOverrides="and|or">
                <if test="username != null and username != ''">
                    username = #{username}
                </if>
                <if test="age != null and age != ''">
                    and age = #{age}
                </if>
            </trim>
        </select>

 当我们if 标签内 and 写在后面的时候,只需要使用 suffixOverrides 就可以达到效果,如下代码所示

<select id="findByNameAndAge" resultType="User">
            select * from user
            <trim prefix="where" suffixOverrides="and|or">
                <if test="username != null and username != ''">
                    username = #{username} and
                </if>
                <if test="age != null and age != ''">
                    age = #{age}
                </if>
            </trim>
        </select>

我们只需要将 prefixOverrides 改为 suffixOverrides就可以达到效果。 

5. choose,when,otherwise

这三个标签一般情况下会一起出现,它与我们Java中 if...else if...else 的功能非常相似。

使用方式如下

这里要注意,<when>标签至少需要写一个,而<othersise>最多只能写一个。

<choose>
    <when test="判断条件">...</when>
    <when test="判断条件">...</when>
    <otherwise>判断条件</otherwise>
</choose>

当我们写这样的一个标签体时,只要有一个条件成立,它就不会再继续向下判断了,直接将满足条件的字段拼接到SQL语句中,也就是说,该标签体内不就算有多个条件都满足,但还是只会执行第一个满足条件的字段查询。

它们也可以搭配<WHERE></WHERE> 或者<trim></trim> 使用,大家可以自由选择,这里我举例使用<WHERE></WHERE>,示例代码举例如下

<select id="findByNameAndAge" resultType="User">
            select * from user
            <where>
                <choose>
                    <when test="username != null and username != ''">
                        username = #{username}
                    </when>
                    <when test="age != null and age != ''">
                        age = #{age}
                    </when>
                    <otherwise>uid = 1</otherwise>
                </choose>
            </where>
        </select>

当我们向上面这样写的时候,username 和 age 的判断只会执行一个,就算用户填写的都是有效数据,我们也会只执行第一个username的判断,所以在开发时需要根据具体的业务场来使用该标签体。如果都不满足,我们可以在 otherwise 中编写一个候选查询条件。

6. foreach

foreach 听名字我们也大概可以猜到它是用来循环的,使用该标签可以实现我们对数据的批量添加和批量删除操作。

 foreach标签也为我们提供了几个属性,下面我会依次说明这些属性是做什么用的

cllection:代表要遍历的数组,Java接口在定义是最好使用@Parm进行标注;

item:表示数组中的每个元素;

open:表示该标签体以什么开头;

close :表示以什么结尾;

separator:表示分隔符是什么;

现在一个场景,根据传输过来的数组中的用户id批量删除这些用户信息。

就此场景,我们就可以使用<foreach>标签来完成;

代码如下

<delete id="deleteListsByUid">
        delete from user where uid in
        <foreach collection="userList" item="uid" open="(" close=")" separator=",">
            #{uid}
        </foreach>
    </delete>

因为我们时批量数据操作,前面有数据库关键字 in ,所以需要加"()",因此则是以 "(" 开头,以 ")" 结尾,所以次数 open = "(",close = ")"。其实 open 和 close也不常用,我们可以自己添加,这里只是给各位说明他俩的作用。

此外,因为数组中有多个数据,因此每个数据在SQL语句中需要使用逗号隔开,因此 separator = ","。

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

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

相关文章

【3D激光SLAM】LOAM源代码解析--laserOdometry.cpp

系列文章目录 【3D激光SLAM】LOAM源代码解析–scanRegistration.cpp 【3D激光SLAM】LOAM源代码解析–laserOdometry.cpp 【3D激光SLAM】LOAM源代码解析–laserMapping.cpp 【3D激光SLAM】LOAM源代码解析–transformMaintenance.cpp 写在前面 本系列文章将对LOAM源代码进行讲解…

什么是回调函数(callback function)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 回调函数&#xff08;Callback Function&#xff09;⭐ 示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这…

Unity中实现获取InputField选中的文字

一&#xff1a;前言 获取到选中的文字&#xff1a;哈哈 二&#xff1a;实现 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition&#xff0c;开始选择时的光标下标和当前光标下标 using UnityEngine; using UnityEngine.EventSystems; using UnityEngin…

记录一个诡异的bug

将对接oa跳转到会议转写的项目oa/meetingtranslate项目发布到天宫&#xff0c;结果跳转到successPage后报错 这一看就是successPage接口名没对上啊&#xff0c;查了一下代码&#xff0c;没问题啊。 小心起见&#xff0c;我就把successPage的方法请求方式从Post改为Get和POST都…

第61步 深度学习图像识别:多分类建模(TensorFlow)

基于WIN10的64位系统演示 一、写在前面 截至上期&#xff0c;我们一直都在做二分类的任务&#xff0c;无论是之前的机器学习任务&#xff0c;还是最近更新的图像分类任务。然而&#xff0c;在实际工作中&#xff0c;我们大概率需要进行多分类任务。例如肺部胸片可不仅仅能诊断…

元矿山下的音视频应用

// 近年来&#xff0c;矿业的技术和管理模式随着元宇宙的火爆和自动驾驶技术的发展逐渐变化、升级&#xff0c;进而衍生出元矿山的概念&#xff0c;音视频技术也在其中成为了关键一环。LiveVideoStackCon 2023 上海站邀请了来自希迪智驾的任思亮&#xff0c;为大家分享希迪智…

算法通过村第三关-数组黄金笔记|数组难解

文章目录 前言数组中出现超过一半的数字数组中只出现一次的数字颜色的分类问题(荷兰国旗问题)基于冒泡排序的双指针&#xff08;快慢指针&#xff09;基于快排的双指针&#xff08;对撞指针&#xff09; 总结 前言 提示&#xff1a;苦不来自外在环境中的人、事、物&#xff0c;…

yolov8热力图可视化

安装pytorch_grad_cam pip install grad-cam自动化生成不同层的bash脚本 # 循环10次&#xff0c;将i的值从0到9 for i in $(seq 0 13) doecho "Running iteration $i";python yolov8_heatmap.py $i; done热力图生成python代码 import warnings warnings.filterwarn…

使用秘籍|如何实现图数据库 NebulaGraph 的高效建模、快速导入、性能优化

本文整理自 NebulaGraph PD 方扬在「NebulaGraph x KubeBlocks」meetup 上的演讲&#xff0c;主要包括以下内容&#xff1a; NebulaGraph 3.x 发展历程NebulaGraph 最佳实践 建模篇导入篇查询篇 NebulaGraph 3.x 的发展历程 NebulaGraph 自 2019 年 5 月开源发布第一个 alp…

【Spring MVC】

目录 &#x1f36e;1 什么是 MVC &#xff1f; &#x1f381;2 Spring MVC 的连接 &#x1f358;2.1 RequestMapping 实现 POST 和 GET 请求 &#x1f963;2.2 GetMapping 只支持 GET 请求 &#x1fad6;2.3 PostMapping 只支持 POST 请求 &#x1f36c;3 Spring MVC 获取参数的…

创建本地镜像

通过前面文章的阅读&#xff0c;读者已经了解到所谓的容器实际上是在父镜像的基础上创建了一个可读写的文件层级&#xff0c;所有的修改操作都在这个文件层级上进行&#xff0c;而父镜像并未受影响&#xff0c;如果读者需要根据这种修改创建一个新的本地镜像&#xff0c;有两种…

Smartbi电子表格软件版本更新,首次推出Excel轻应用和语音播放

Smartbi电子表格软件又又又更新啦&#xff01; 此次更新&#xff0c;首次推出了新特性——Excel轻应用和语音播报。另外&#xff0c;还对产品功能、Demo示例、配套文档进行了完善和迭代。 低代码开发Excel轻应用 可实现迅速发布web应用 业务用户的需求往往都处于“解决问题”…

APP调用bindService的跨进程调用过程

app执行bindService时会经过如下8次跨系统进程调用过程&#xff1a; 第1步&#xff1a;通过AMS.getService跨进程调用 第2步&#xff1a;AMS返回它的IBinder 第3步&#xff1a;通过AMS的IBinder调用AMS的bindService方法 第4步&#xff1a;而AMS存放有Server端的IBinder&…

ChatGPT在医疗系统的应用探索动态

注意&#xff1a;本信息仅供参考&#xff0c;发布该内容旨在传递更多信息的目的&#xff0c;并不意味着赞同其观点或证实其说法。 生成式人工智能&#xff0c;如OpenAI开发的ChatGPT&#xff0c;被认为是可以颠覆医疗行业的工具。尽管该技术刚刚起步&#xff0c;但已有许多医…

Vue2向Vue3过度Vuex核心概念mutations

目录 1 核心概念-mutations1.定义mutations2.格式说明3.组件中提交 mutations4.练习5.总结 2 带参数的 mutations1.目标&#xff1a;2.语法2.1 提供mutation函数&#xff08;带参数&#xff09;2.2 提交mutation 3 练习-mutations的减法功能1.步骤2.代码实现 4 练习-Vuex中的值…

kettle实现爬虫

步骤概览 获取请求 请求地址 东方财富网股票请求 自定义常量数据 获取HTTP请求之前&#xff0c;必须先定义一个URL常量作为HTTP client的输入 HTTP client 注&#xff1a;此处得到的数据并不是原生的json字符串&#xff0c;自己可以用文本文件输出测试以下。如下图 JavaScri…

Vue2向Vue3过度核心技术路由

目录 1 路由介绍1.思考2.路由的介绍3.总结 2 路由的基本使用1.目标2.作用3.说明4.官网5.VueRouter的使用&#xff08;52&#xff09;6.代码示例7.两个核心步骤8.总结 3 组件的存放目录问题1.组件分类2.存放目录3.总结 4 路由的封装抽离5 Vue路由-重定向1.问题2.解决方案3.语法4…

谈谈子网划分的定义、作用、划分方式以及案例

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、子网划分的定义 二、子网掩码的作用 1、…

林业气象站——林业种植气象观测

林业气象站是一种用于观测林区气象环境的仪器&#xff0c;能够观测林区天气、土壤等自然环境参数&#xff08;温度、湿度、风速、风向、降雨量、气压、放射线、土壤湿度等&#xff09;&#xff0c;为开展环境观测、天气预报、灾害预警、林区虫害防治起到综合指导作用。 林业气…