MyBatis操作数据库(4)

动态sql

动态sql是MyBatis的强大特性之一, 能够完成不同条件下的sql拼接.

<if>标签

在注册用户的问题时, 可能会有这样的一个问题:就是说注册时有一些信息是必填的, 而有一些信息是选填的. 那么如果在添加用户的时候有不确定字段的传入, 程序应该如何实现呢?

这时就可以使用动态标签来判断了, 比如添加的时候, 性别gender为非必填字段, 我们通过使用<if>标签来指定这个非必填的内容, 它的语法格式如下:

<if test="条件">语句</if>: 如果test后面的条件成立的话, 就会拼接if标签里的语句.

接口定义:

Integer insertByCondition(UserInfo userInfo);

Mapper.xml实现:

<insert id="insertUserByCondition">
    INSERT INTO userinfo (
    username,
    `password`,
    age,
    <if test="gender != null">
        gender,
    </if>
    phone)
    VALUES (
    #{username},
    #{age},
    <if test="gender != null">
        #{gender},
    </if>
    #{phone})
</insert>

该实现是能够解决一些非必填的情况的, 但是如果有多个, 甚者是拼接在头尾的, 有时就可能出现问题, 比如说:

1.如果phone也是非必填字段, 但最后并没有填, 这就会使得gender后面的 , 结尾的情况下导致sql语句错误. 但也有老铁们就要说了, 我就不能把 , 都放在每个字段的前面吗(除了username)?这就是2的问题

2.如果username也是非必填, 但是最后没有填, 后面的有些填了, 这就使得会出现 , 开头的情况, 也会导致语法错误.

<trim>标签 

之前的用户插入功能, 只是有一个gender字段可能是选填项, 如果有多个字段, 一般考虑使用标签结合标签,  对多个字段都产生动态生成的方式.

标签中有如下属性:

prefix: 表示整个语句块, 以prefix的值作为前缀.

suffix: 表示整个语句块, 以suffix的值作为后缀.

prefixOverrides: 表示整个语句块要去掉的前缀.

suffixOverrides: 表示整个语句块要去掉的后缀

有了这个, 上面的问题也就迎刃而解了, 我们通过可以设置逗号为前缀/后缀的方式灵活地操作逗号的存在, 具体的语句如下:

    <insert id="insertByCondition">
        insert into userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null">
                username,
            </if>
            <if test="password != null">
                password,
            </if>
            <if test="age != null">
                age,
            </if>
            <if test="gender != null">
                gender,
            </if>
            <if test="phone != null">
                phone,
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username != null">
                #{username},
            </if>
            <if test="password != null">
                #{password},
            </if>
            <if test="age != null">
                #{age},
            </if>
            <if test="gender != null">
                #{gender},
            </if>
            <if test="phone != null">
                #{phone},
            </if>
        </trim>
    </insert>

具体来说, 在以上sql动态解析时, 会将第一个部分做如下处理:

基于prefix配置, 开始部分加上 (

基于suffix配置, 结束部分加上 )

多个组织的语句都以逗号结尾, 在最后拼接好的字符串还会以逗号结尾, 会基于suffixOverrides配置去掉最后一个逗号. 

特别注意: <if test="usernae != null">中的username是传入对象的属性.

<where>标签

看下面这个场景, 系统会根据我们的筛选条件, 动态组装where条件.

接下来看代码实现:

需求: 传入的用户对象, 根据属性做where条件查询, 用户对象中属性不为null的, 都为查询条件. 如果username为"a", 则查询条件为where username = "a", 如果有多个条件, 中间会拼接"and".

原有sql:

SELECT
    *
FROM
    userinfo
WHERE
    age = 18
    AND gender = 1
    AND delete_flag =0

接口定义:

List<UserInfo> queryByCondition();

Mapper.xml实现:

    <select id="queryUserByCondition" resultType="com.bit.mybatis.testmybatis.model.UserInfo">
        select * from userinfo
        <where>
            <if test="age != null">
                age = #{age}
            </if>
            <if test="gender != null">
                and gender = #{gender}
            </if>
            <if test="deleteFlag != null">
                and delete_flag = #{deleteFlag}
            </if>
        </where>
    </select>

<where>只会在子元素有内容的情况下才插入where子句, 而且会自动去除子句的开头AND或OR

以上标签也可以使用<trim prefix="where" prefixOverrides="and">替换, 但是此种情况下, 当子元素都没有内容时, where关键字也会保留. 

<set>标签

需求: 根据传入的用户对象属性来更新用户数据, 可以使用标签来指定动态内容.

接口定义: 根据传入的用户id属性, 修改其它不为null的属性.

Integer updateUserByCondition(UserInfo userInfo);

Mapper.xml

    <update id="updateByCondition">
        update userinfo
        <set>
            <if test="username != null">
                username = #{username},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
        </set>
        where id = #{id}
    </update>

<set>:动态地在SQL语句中插入set关键字, 并删掉额外的逗号.(用于update语句中).

以上标签也可以使用<trim prefix="set" suffixOverrides=",">替换 

<foreach>标签

之前我们在MySQL中学习条件查询的时候, 学到过类似 in (a, b, c, d)这样的语句, 表示满足任意一个条件, 都会返回true. 

对集合进行遍历时可以使用该标签. 该标签有如下属性:

collection: 绑定方法参数中的集合, 如List, Set, Map或数组对象

item:遍历时的每个对象

open: 语句块开头的字符串

close: 语句块结束的字符串

separator: 每次遍历之间间隔的字符串.

 需求: 根据多个userid,删除用户数据:

接口方法:

void deleteByIds(List<Integer> ids);

ArticleMapper.xml中新增删除sql:

    <delete id="batchDelete">
        delete from userinfo
        where id in
<!--        (1, 2, 3, 4)-->
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>

<include>标签

问题分析: 

在xml映射文件中配置的SQL, 有时可能会存在很多的重复片段, 此时就会存在很多冗余的代码

我们可以对重复的代码片段进行抽取, 将其通过<sql>标签封装到同一个SQL片段, 然后通过<include>标签进行引用.

<sql>:定义可重用的SQL片段.

<include>: 通过属性refid, 指定包含的SQL片段. 

<sql id="allColumn">
    id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>

通过<include>标签在原来抽取的地方进行引用. 操作如下:

<select id="queryAllUser" resultMap="BaseMap">
    select
    <include refid="allColumn"></include>
    from userinfo
</select>

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

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

相关文章

单调队列(C/C++)

引言&#xff1a; 单调队列和单调栈都是一种数据结构&#xff0c;应用十分广泛&#xff0c;在蓝桥杯、ICPC、CCPC等著名编程赛事都是重点的算法&#xff0c;今天博主将自己对单调栈与单调队列的理解以及刷题的经验&#xff0c;用一篇博客分享给大家&#xff0c;希望对大家有所…

第七、八章 函数 + 文件

第七章 函数 多个返回值 def test_return():return 1, "hello", Truex,y,z test_return() print(x) print(y) print(z) 1 hello True 传入的参数 位置参数 定义&#xff1a;调用函数时根据函数定义的参数位置来传递参数要求&#xff1a;传递的参数和定义的参数的顺…

1.C++入门

1.关键字&#xff08;C98&#xff09; 2.命名空间 在 C/C 中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存 在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是 对标识符的名称进行本地化 &#xff…

利用 Amazon ECS 进行分布式机器学习

本文作者 Santiago Flores Kanter 亚马逊云科技高级解决方案架构师 Ravi Yadav 亚马逊云科技首席容器专家 校译作者 梁宇 亚马逊云科技专业服务团队 DevOps 顾问 在 Amazon ECS 服务上运行分布式机器学习工作负载可让 ML 团队更加专注于创建、训练和部署模型&#xff0c;而不是…

搭建PyTorch神经网络进行气温预测(手写+调包两种方法)(保证学会!)+找到神经网络的最优情况

代码上有注释&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 本篇主要包括三大部分&#xff1a; 第一部分&#xff1a;导入数据集导入第三方库数据集简单介绍与可视化数据集简单预处理 第二部分&#xff1a;手写神经网络代码实现气温预测&#…

链表传一级指针以及leetcode做题有感

上个文章说要传二级指针&#xff0c;经过一段时间的学习之后才知道可以传一级指针&#xff1a; 之所以要传二级指针&#xff0c;是要改变一级指针的值&#xff0c;也就是把头节点的指针改变&#xff0c;如图&#xff1a; 从左边到右边&#xff0c;头指针 一级指针plist 的值发…

C++算法题 - 哈希表

目录 383. 赎金信205. 同构字符串290. 单词规律242. 有效的字母异位词49. 字母异位词分组1. 两数之和202. 快乐数219. 存在重复元素Ⅱ128. 最长连续序列 383. 赎金信 LeetCode_link 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 m…

道合顺传感新品上市!高性能氢气传感器DSB14-G3K-J详解

道合顺传感高性能氢气传感器DSB14-G3K-J正式发布&#xff01;超强抗干扰能力优势明显。应对氢气安全挑战、高性能氢气传感器国产化、为储能保驾护航。 氢气&#xff0c;作为现今能源领域中的新贵&#xff0c;在储能行业中应用广泛且备受瞩目。但氢气易燃、易爆特性使其在生产、…

gradle.properties 中文字符乱码问题

我用AS开发Android应用。在gradle.properties中输入中文&#xff0c;再次打开时&#xff0c;发现中文变成了&#xff1f;&#xff1f;&#xff1f;。上网查询&#xff0c;发现了一个解决办法&#xff1a; 在菜单File-Settings-Editor-File Encodings中&#xff0c;将“Default…

【复习笔记】FreeRTOS(五)时间片调度

本文是FreeRTOS复习笔记的第五节&#xff0c;时间片调度。 上一篇文章&#xff1a; 【复习笔记】reeRTOS(四) 列表项的插入和删除 文章目录 1.时间片调度简介1.1. 运行过程 二、实验设计三、测试例程四、实验效果 1.时间片调度简介 FreeRTOS支持多个任务同时拥有一个优先级&am…

春藤实业启动SAP S/4HANA Cloud Public Edition项目,与工博科技携手数字化转型之路

3月11日&#xff0c;广东省春藤实业有限公司&#xff08;以下简称“春藤实业”&#xff09;SAP S/4HANA Cloud Public Edition&#xff08;以下简称“SAP ERP公有云”&#xff09;项目正式启动。春藤实业董事长陈董、联络协调项目经理慕总、内部推行项目经理陈总以及工博董事长…

数仓建模—数据架构

数仓—数据架构 为了在企业决策中使用数据,数据必须经过整个数据平台的各个阶段。整个过程是什么样子的,从开始到结束?原始形式的数据是如何转化为可导致商业决策的见解的?这些问题可以通过数据架构来回答。 数据架构是指记录组织所有数据资产的模型、规则和标准。它映射…

Web前端-JavaScript

黑马程序员JavaWeb开发教程 文章目录 一、js引入方式1、内部脚本2、外部脚本 二、js基础语法1、书写语法&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;输出语句 2、变量&#xff08;1&#xff09;变量&#xff08;2&#xff09;注意事项 3、数据类型、运算符、流…

spring-数据处理及跳转

结果跳转方式 ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 . 页面 : {视图解析器前缀} viewName {视图解析器后缀} <!-- 视图解析器 --> <bean class"org.springframework.web.servlet.view.InternalResourceViewRes…

Java定时任务

一、java.util.Timer java.util.Timer 类允许您在未来的某个时间执行一个任务&#xff0c;或者在一定的时间间隔执行任务。您可以创建一个 Timer 实例&#xff0c;并调用其 schedule() 方法来安排任务的执行。这种方式比较简单&#xff0c;但在高并发环境下可能不够灵活。 1.…

Git学习与码云实战

Git学习与码云实战 Git安装 概述&#xff1a; Git 是一个开源的分布式版本控制系统&#xff0c;可以有效、高速的处理从很小到非常大的项目版本管理&#xff0c;是目前使用范围最广的版本管理工具。 下载安装&#xff1a; 下载地址&#xff1a;https://git-scm.com/ 下载后傻瓜…

李彦宏:开源模型会越来越落后

李彦宏&#xff1a;开源模型会越来越落后 昨天听完的李总讲座 大家以前用开源觉得开源便宜&#xff0c;其实在大模型场景下&#xff0c;开源是最贵的。所以&#xff0c;开源模型会越来越落后。 ——李彦宏 至于开源还是闭源&#xff0c;这和企业的利益息息相关。 随着科技的迅猛…

双向链表详解

一.双向链表结构 我们一般所说的双向链表是带头循环双向链表&#xff0c;这里的带头更我们之前的头节点不是一回事。带头链表里的头节点&#xff0c;实际上为哨兵位&#xff0c;哨兵位的头节点种是不存放任何有效数据的&#xff0c;只是站在这里起到放哨的作用。 哨兵位的意义…

【C++从练气到飞升】08---模板

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书。 目录 一、泛型编程 什么是泛型编程: 二、函数模板 1. 函数模板概念 2. 函数模板格式 3. 函数模板的原理 4. 函数模板的实例…

Nginx part2.2

目录 如何用Nginx搭建多网址服务器&#xff1f; 基于ip地址的虚拟主机 1. 先建立存储网页的目录 2.进行子配置 3.编写.conf文件 基于端口号的虚拟主机 基于域名的虚拟主机 如何用Nginx搭建多网址服务器&#xff1f; 有些网站&#xff0c;ip不同&#xff0c;域名不同&…