MyBatis 操作数据库(构造动态 SQL)

news2024/11/18 18:44:01

前言

        动态 SQL 是 Mybatis 的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接。

<if> 标签

        我们在填写用户信息的时候经常会看到如下的界面,用户信息中包含必填信息和非必填信息,非必填信息是填和不填都可以的,那这样的话插入到数据库中的数据有多种情况,SQL 语句也有多种情况,比如地址管理,我可以选择填,也可以选择不填,那么 SQL 语句的插入语句就要对应插入或者不插入

        要想完成这个效果,我们就需要构造动态 SQL

接口定义:

//通过用户提供的数据,动态构造 SQL 语句进行插入
Integer insertUserByCondition(UserInfo userInfo);

Mapper.xml实现:

<insert id="insertUserByCondition">
        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>

         <if> 标签的 test 属性表示判断的内容,如下的代码,判断参数 username 的值是否为 null,相当于判断用户是否输入 username,如果不为 null,说明用户输入了 username ,就需要插入数据到 username 字段,所以拼接 username, 到 SQL 语句中

<if test="username!=null">
    username,
</if>

        如果所有的参数都赋了值,构造的 SQL 语句就是:

insert into userinfo( username, password, age, gender, phone )
values(#{username},#{password},#{age},#{gender},#{phone});

        如果参数 gender 和 phone 都没赋值,就是:

insert into userinfo( username, password, age)
values(#{username},#{password},#{age});

        构造的 SQL 语句是根据用户的输入动态改变的

<trim> 标签

        在上面 Mapper.xml 实现的代码中,我们用到了 <trim>  标签

标签中有如下属性:

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

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

• prefixOverrides:表⽰整个语句块要去除掉的前缀

• suffixOverrides:表⽰整个语句块要去除掉的后缀

       在上面 Mapper.xml 实现的代码中,我们使用了<trim> 标签进行了以下处理

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

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

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

<where> 标签

        <where> 标签只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的 AND 或 OR

        看下⾯这个场景, 系统会根据我们的筛选条件, 动态组装 select 语句的 where 条件,来查询到我们指定的内容

        假设所有的参数都输入,我们得到的 SQL 语句如下:

SELECT id,username,password,age,gender,phone,delete_flag,create_time,update_time 
FROM userinfo 
WHERE id = #{id}
AND username = #{username} 
AND gender = #{gender};

        接口定义:

 //通过用户提供的数据,动态构造 SQL 语句进行查询
List<UserInfo> selectByCondition(UserInfo userInfo);

        Mapper.xml实现:

    <select id="selectByCondition" resultType="com.example.springbootdemo.dao.UserInfo">
        select id,username,password,age,gender,phone,delete_flag,create_time,update_time
        from userinfo
        <where>
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="gender!=null">
                and gender=#{gender}
            </if>
        </where>
    </select>

        假设用户一个参数都没有输入,得到的 SQL 语句就是:

select id,username,password,age,gender,phone,delete_flag,create_time,update_time
from userinfo;

        假设用户没有输入 id 参数,得到的 SQL 语句就是:

SELECT id,username,password,age,gender,phone,delete_flag,create_time,update_time 
FROM userinfo 
WHERE username = #{username} 
AND gender = #{gender};

<set>标签

         <set>标签动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号.(⽤于update语句中)

        根据用户传入的参数,动态构造 SQL 语句,插入相关内容

        接⼝定义:根据传⼊的用户 id 属性,修改其他传入参数的属性

//通过用户提供的数据,动态构造 SQL 语句进行修改
Integer updateByCondition(UserInfo userInfo);

        Mapper.xml实现:

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

<foreach> 标签

对集合进⾏遍历时可以使⽤该标签。

标签有如下属性:

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

• item:遍历时的每⼀个对象 

• open:语句块开头的字符串 

• close:语句块结束的字符串 

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

        有以下场景我们将要删除的用户 id 都集中放到一个 List<Integer> 列表当中,在删除的时候,将列表中的用户 id 所指向的信息都进行删除

        假设列表当中的数据为{1,2,3,4,5},我们要构造的 SQL 语句就应该为:

delete from userinfo where id in(1,2,3,4,5);

        接口定义:

//给定一个 id 集合,将集合中的所有 id 对应的用户数据都删除
Integer deleteByIds(List<Integer> ids);

        Mapper.xml实现:

    <delete id="deleteByIds">
        delete from userinfo
               where id in
                     <foreach collection="ids" item="id" separator="," open="(" close=")">
                         #{id}
                     </foreach>
    </delete>

       根据一开始提到的例子,我们通过 <foreach> 标签要构造出来的 SQL 结构应该为 (1,2,3,4,5),1,2,3,4,5 要通过遍历集合中的内容获得、

collection="ids" 表示绑定了参数中的集合 ids 

item="id" 表示遍历集合得到的数据放到 id 中,通过 id 来使用

separator=","  遍历集合得到的数据之间通过  , 进行分割

open="("  <foreach> 标签包含的语句块以 "(" 作为开头

close=")"  <foreach> 标签包含的语句块以 ")" 作为结尾

<sql> 和 <include> 标签

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

        我们可以通过 <sql> 标签提取重复的 SQL 片段进行封装,通过 <include> 标签引用封装好的 SQL 片段

        通过 <sql> 标签封装:

        通过 id 属性为封装的 SQL 片段命名,方便后续进行调用

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

        通过 <include> 标签引用:

        通过 refid 属性设置要引入的 SQL 片段

    <select id="selectByCondition2" resultType="com.example.springbootdemo.dao.UserInfo">
        select 
            <include refid="allColumn"></include>
            from userinfo
    </select>

         最终得到的 SQL 语句为:

select id,username,password,age,gender,phone,delete_flag,create_time,update_time
from userinfo;

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

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

相关文章

UDS 14229-1定义的请求的响应行为

UDS服务响应规则 重要提示服务器一般响应行为包含子功能的请求响应行为物理寻址请求功能寻址请求 没有子功能参数的服务响应行为物理寻址客户端请求功能寻址客户端请求 伪代码示例 重要提示 服务应当支持物理寻址方式请求&#xff0c;部分服务也支持功能寻址方式请求。在功能寻…

Linux tc 使用

tc模拟延时丢包等网络故障依赖的内核驱动 /lib/modules/5.15.0-52-generic/kernel/net/sched/sch_netem.ko有些系统并不是默认就安装上该驱动的&#xff0c;如果没有安装该驱动&#xff0c;构造网络故障时会报错。 root:curtis# tc qdisc change dev enp4s0 root netem delay…

LoRA低秩微调技术详解

在当今快节奏的技术环境中&#xff0c;大型AI模型正在推动不同领域的突破。 然而&#xff0c;根据特定任务或数据集定制这些模型可能是一项计算和资源密集型工作。 LoRA是一种突破性且高效的微调技术&#xff0c;它利用这些高级模型的强大功能来执行自定义任务和数据集&#xf…

Word 2016 删除标注

步骤&#xff1a; 菜单栏--审阅--删除--删除文档中的所有标注

07.webpack的性能优化 -- 产出代码

目标&#xff1a; 体积更小合理分包&#xff0c;不重复加载速度更快&#xff0c;使用内存更小 实现功能 小图片的base64编码提取公共代码bundle加hashIngorePlugin懒加载使用CDN使用productionScope Hosting 1. 使用production module.exports smart(webpackCommonConf, …

Python武器库开发-flask篇之session与cookie(二十六)

flask篇之session与cookie(二十六) 在 Flask 中&#xff0c;可以使用 session 来在不同请求之间存储和传递数据。Session 在客户端和服务器端之间交换&#xff0c;但是数据存储在服务器端。 Session 与 Cookie 的区别 session 和 cookie 都可以用来在不同请求之间存储和传递…

Vue3-readonly(深只读) 与 shallowReadonly(浅只读)

Vue3-readonly(深只读) 与 shallowReadonly&#xff08;浅只读&#xff09; readonly(深只读)&#xff1a;具有响应式对象中所有的属性&#xff0c;其所有值都是只读且不可修改的。shallowReadonly(浅只读)&#xff1a;具有响应式对象的第一层属性值是只读且不可修改的&#x…

解决Kibana初始化失败报错: Unable to connect to Elasticsearch

现象&#xff1a; 原因&#xff1a; docker run生成容器的时候&#xff0c;指定elastic server时指向了localhost 为什么不能是localhost, 因为这个localhost指向的是容器本身的网络&#xff0c;而elastic用的是物理网络&#xff0c;两个网络是隔离的&#xff0c;所以如果kiba…

Rocket如何实现顺序消费

RocketMQ 支持两种消息模式 集群消费&#xff08; Clustering &#xff09;和广播消费&#xff08; Broadcasting &#xff09;。 集群消费&#xff1a;同一 Topic 下的一条消息只会被同一消费组中的一个消费者消费。也就是说&#xff0c;消息被负载均衡到了同一个消费组的多…

Java集合大总结——Collection接口

集合概述 Java 集合可分为 Collection 和 Map 两大体系&#xff1a; Collection接口&#xff1a;用于存储一个一个的数据。 List子接口&#xff1a;用来存储有序的、可以重复的数据&#xff08;主要用来替换数组&#xff0c;也被称作"动态"数组&#xff09; 实现类…

LangChain 代理 Agent(学习笔记)

原文&#xff1a;LangChain 代理 Agent(学习笔记) - 尘叶心繁的专栏 - TNBLOG LangChain 代理 Agent(学习笔记) LangChain 代理 Agent(学习笔记) 简介Agent Zero-shot ReActStructured Input ReActOpenAI FunctionsConversationalSelf ask with searchReAct document storePlan…

斯坦福机器学习 Lecture1 (机器学习,监督学习、回归问题、分类问题定义)

https://www.bilibili.com/video/BV1JE411w7Ub?p1&vd_source7a1a0bc74158c6993c7355c5490fc600 笔记如下 机器学习的定义&#xff1a;不需要明确编程就能让计算机去学习做某件事情 另一个定义 什么是监督学习&#xff1f; 给定一组 (x,y) 样本&#xff0c;学习一个 x-&g…

十三、Linux文件目录指令

pwd 指令 基本语法&#xff1a;pwd &#xff08;功能描述&#xff1a;显示当前工作目录的绝对路径&#xff09; 应用实例&#xff1a;案例&#xff1a;显示当前工作目录的绝对路径 ls 指令 基本语法&#xff1a;ls 【选项】【目录或是文件】 常用选项 -a &#xff1a;显示当…

【STL】string类 (上) <vector>和<list>的简单使用

目录 一&#xff0c;什么是 STL 二&#xff0c;STL 的六大组件 三&#xff0c;标准库中的 string 类 1&#xff0c;string 类 2&#xff0c;string 类的常用接口 1&#xff0c;string类对象的常见构造 2&#xff0c;string&#xff08;const string& str&#xff…

PHP常用的数组函数

PHP是一种流行的服务器端脚本语言&#xff0c;广泛用于Web开发。数组是PHP中最重要且最常用的数据类型之一&#xff0c;它提供了许多强大的数组函数&#xff0c;用于在数组上执行各种操作。在本文中&#xff0c;我们将深入解析PHP中一些常用的数组函数&#xff0c;以便更好地理…

【考研数学神作】你不能错过的学习教材

【文末送书】今天推荐一些考研数学优质书籍&#xff0c;带你筑牢知识体系 目录 导语优美的数学思维&#xff1a;问题求解与证明数学分析线性代数线性代数及其应用代数初等数论及其应用数论概论概率论基础教程概率论与统计推断统计学基础&#xff1a;透过数据看世界数理统计及其…

前端为什么要工程化

前端为什么要工程化 文章目录 前端为什么要工程化传统开发的弊端一个常见的案例更多问题 工程化带来的优势开发层面的优势团队协作的优势统一的项目结构统一的代码风格可复用的模块和组件代码健壮性有保障团队开发效率高 求职竞争上的优势 现在前端的工作与以前的前端开发已经完…

【Seata源码学习 】篇三 seata客户端全局事务开启、提交与回滚

1.GlobalTransactionalInterceptor 对事务方法对增强 我们已经知道 GlobalTransactionScanner 会给bean的类或方法上面标注有GlobalTransactional 注解 和 GlobalLock的 添加一个 advisor &#xff08;DefaultPointcutAdvisor ,advisor 绑定了PointCut 的 advise) 而此处的 …

更新文章分类

CategoryController PutMappingpublic Result update(RequestBody Validated Category category){categoryService.update(category);return Result.success();} CategoryService //更新分类void update(Category category); CategoryServiceImpl Overridepublic void update(…

大数据Doris(二十六):数据导入(Routine Load)介绍

文章目录 数据导入(Routine Load)介绍 一、​​​​​​​适用场景