MyBatis 实现动态 SQL

 MyBatis 中的动态 SQL 就是SQL语句可以根据不同的情况情况来拼接不同的sql。

本文会介绍 xml注解 两种方式的动态SQL实现方式。

XML的实现方式

先创建一个数据表,SQL代码如下:

DROP TABLE IF EXISTS `userinfo`;
CREATE TABLE `userinfo`  (`id` int(11) NULL DEFAULT NULL,`username` varchar(127) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`gender` tinyint(4) NULL DEFAULT NULL COMMENT '1-男 2-⼥ ',`delete_flag` tinyint(4) NULL DEFAULT 0 COMMENT '0-正常, 1-删除',`create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP,`update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

数据库表和JAVA对象的对应如下:

 

平时在注册账号时会有一些非必填项,而我们就可以使用 <if> 标签来跟据条件进行动态的SQL语句的添加。

接口定义:

@Mapper
public interface Userinfo {Integer addUserinfo(User user);
}

<if>标签

语法:

<if test = "条件"> 语句块 </if>

如果 test 后面的条件判断结果为 true,那么就将后面的语句块拼接到最终的 SQL 语句中。

XML的实现代码如下:

<insert id="addUserinfo">insert into userinfo(id, username,<if test="gender != null">gender,</if><if test="deleteFlag != null">delete_flag</if>) values (#{id},#{username},<if test="gender != null">#{gender},</if><if test="deleteFlag != null">#{deleteFlag}</if>);
</insert>

注意:test中的gender和deleteFlag,是传入对象中的属性,不是数据库字段。

执行以下测试代码:

@Test
void addUserinfo() {User user = new User();user.setId(2);user.setUsername("zhangsan");user.setDeleteFlag(0);//此时gender为空userinfo.addUserinfo(user);
}

运行之后我们从日志中可以看出最终执行的SQL语句中并没有 gender

而当我们令gender不为空:

user.setGender(1);

但是此时我们的代码还有一个隐藏BUG,比如当deleteFlag为空时:

@Test
void addUserinfo() {User user = new User();user.setId(2);user.setUsername("zhangsan");//user.setDeleteFlag(0);user.setGender(1);//此时deleteFlag为空userinfo.addUserinfo(user);
}

此时代码报错了,我们可以从MyBatis打印的日志中看出SQL语句出现了多余的逗号。

此时就需要使用<trim>标签

<trim>标签

<trim>标签中有如下属性:

  • prefix:表示在整个语句块起始位置加上prefix的值作为前缀
  • suffix:表示在整个语句块结尾加上suffix的值作为后缀
  • prefixOverrides:如果整个语句块的前缀等于prefixOverrides的值,去掉prefixOverrides的值;
  • suffixOverrides:如果整个语句块的后缀等于suffixOverrides的值,去掉suffixOverrides的值。

我们利用<trim>标签来将上述SQL中结尾的 ‘,’ 去除

<insert id="addUserinfo">insert into userinfo <trim prefix="(" suffix=")" suffixOverrides=",">id, username,<if test="gender != null">gender,</if><if test="deleteFlag != null">delete_flag</if></trim>values<trim prefix="(" suffix=");" suffixOverrides=",">    #{id},#{username},<if test="gender != null">#{gender},</if><if test="deleteFlag != null">#{deleteFlag}</if></trim>
</insert>

此时程序就可以正常执行了。

<where>标签

<where>标签一般应用于需要动态组装where条件的地方。

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

例如:我们此时根据 id 和 gender 来查找数据。

数据库中的数据如下:

接口定义:

User selectUser(Integer id, Integer gender);

xml实现:

<select id="selectUser" resultType="com.example.Spring_demo.mySQL.User">select * from userinfo<where><if test="id != null">id=#{id}</if><if test="gender != null">and gender=#{gender}</if></where>;
</select>

JAVA测试代码

@Test
void selectUser() {System.out.println(userinfo.selectUser(1, 1));
}

从打印的结果和日志中我们可以看出结果正确。

如果 id 和 gender 都为 null

@Test
void selectUser() {System.out.println(userinfo.selectUser(null, null));
}

虽然程序报错了,可是并不是因为SQL错了而是因为接收的参数报错。

此时可以看出 where 被去掉了。 

此时如果 gender 为空

@Test
void selectUser() {System.out.println(userinfo.selectUser(1, null));
}

<where>标签并不能去除句末的 and 

<set>标签

<set>标签用于动态更新数据

用于 update 语句中动态的在SQL语句中插入 set 关键字,并会删掉额外的逗号。

例如:根据传入的id属性,修改 username 和 gender 中不为null的属性。

接口定义:

Integer upData(Integer id, String username, Integer gender);

xml代码实现:

<update id="upData">update userinfo  <set><if test="username != null">username = #{username},</if><if test="gender != null">gender = #{gender}</if></set>where id = #{id};
</update>

JAVA测试代码

void upData() {//gender为空userinfo.upData(2, "xiaohong", null);
}


可以看出删掉了额外的逗号(前后都会删掉)。

<foreach>标签

该标签可以在对集合进行遍历时使用。

标签有如下属性:

  • collection:绑定方法参数中的集合,如List,Set,Map或数组对象;
  • item:遍历时对象中的每个元素;
  • open:语句块开头的字符串;
  • close:语句块结束的字符串;
  • separator:每次遍历之间间隔的字符串。

例如:批量删除数据

接口定义:

Integer deleteUsers(List<Integer> ids);

xml代码实现:

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

注意:这两个地方的名称必须相同。

JAVA测试代码

@Test
void deleteUsers() {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);userinfo.deleteUsers(list);
}

<include>和<SQL>标签

这两个标签配合使用可以实现对重复的代码片段进行抽取,将其通过 <sql> 标签封装到一个SQL片段,然后再通过<include> 标签进行引用。用来降低代码的冗余度。

  • <sql> :定义可重用的SQL片段
  • <include> :通过属性refid,指定包含的SQL片段

例如:我们可以抽取下面xml中的部分代码。

<delete id="deleteUsers">delete from userinfo where id in<foreach collection="ids" item="id" open="(" close=");" separator=",">#{id}</foreach>
</delete>
<sql id="aaa">delete from userinfo where id in
</sql><delete id="deleteUsers"><include refid="aaa"></include><foreach collection="ids" item="id" open="(" close=");" separator=",">#{id}</foreach>
</delete>

 JAVA测试代码

@Test
void deleteUsers() {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);userinfo.deleteUsers(list);
}

@注解的实现方式

注解的实现其实非常简单只需把xml标签中的SQL(包括标签),使用<script></script> 标签括起来就可以了。

例如下面的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>

注解的实现方法:

@Insert("<script>" +"INSERT INTO userinfo (username,`password`,age," +"<if test='gender!=null'>gender,</if>" +"phone)" +"VALUES(#{username},#{age}," +"<if test='gender!=null'>#{gender},</if>" +"#{phone})"+"</script>")
Integer insertUserByCondition(UserInfo userInfo);

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

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

相关文章

Mac上几款好用的MacBook视频播放器

使用Mac电脑时&#xff0c;视频播放器可以说是我们使用频率最高的软件之一了&#xff0c;不管是工作时看视频资料还是在家里看下载好的电影&#xff0c;都需要用到视频播放器&#xff0c;本文中我们就来推荐几款好用的Macbook视频播放器&#xff0c;总有一款适合你&#xff01;…

centos ssh 默认端口 修改

centos7更改SSH端口-腾讯云开发者社区-腾讯云 (tencent.com) linux centos修改ssh端口号_semanage port -a -t ssh_port_t -p tcp-CSDN博客

数据结构——B/顺序表和链表

&#x1f308;个人主页&#xff1a;慢了半拍 &#x1f525; 创作专栏&#xff1a;《史上最强算法分析》 | 《无味生》 |《史上最强C语言讲解》 | 《史上最强C练习解析》 &#x1f3c6;我的格言&#xff1a;一切只是时间问题。 ​ 1.线性表 线性表&#xff08;linear list&…

QXlsx Qt操作excel(1)

QXlsx 是一个用于处理Excel文件的开源C库。它允许你在你的C应用程序中读取和写入Microsoft Excel文件&#xff08;.xlsx格式&#xff09;。该库支持多种操作&#xff0c;包括创建新的工作簿、读取和写入单元格数据、格式化单元格、以及其他与Excel文件相关的功能。 关于QXlsx的…

SQL拆分字段内容(含分隔符)

问题描述&#xff1a; 在做数据迁移的过程中&#xff0c;我们希望对表中的某个字段根据分隔符进行拆分&#xff0c;得到多条数据&#xff0c;原代码有点意思&#xff0c;因此记录一下。 我们假设某条数据如下&#xff1a; IDSTRS1公司名称不能小于四个字&#xff0c;行业类别…

【OrangePi Zero2的系统移植】OrangePi Zero2 SDK说明

一、使用环境要求 二、获取Linux SDK 三、首次编译完整SDK 基于OrangePi Zero2的系统移植 之前我们讲解香橙派的使用时&#xff0c; 都是直接在香橙派上进行代码编译&#xff0c; 但在实际的项目开发过程中&#xff0c;更多 的还是使用交叉编译环境进行代码的编译。再编译完成…

卷积层Conv1d包含的元素分别是什么,经过卷积层,数据的形状发生变化吗?

nn.Conv1d 是一个一维卷积层&#xff0c;它通常用于处理序列数据&#xff0c;如时间序列或文本数据。这个层包含以下主要元素&#xff1a; 输入通道数&#xff08;In_channels&#xff09;&#xff1a;这是输入数据的通道数。对于单通道数据&#xff08;如灰度图像或单变量时间…

医学三基答案在哪搜?4个大学生必备的搜题 #知识分享#职场发展

今天&#xff0c;我将分享一些受欢迎的、被大学生广泛使用的日常学习工具&#xff0c;希望能给你的学习生活带来一些便利和启发。 1.颐博咨询 这是一个网站 找题好用的在线搜题站,快考不限次搜题助手,问题截图搜题软件,练题通关考试试题大全。 2.题小聪 这是一个公众号 这…

macbookair怎么清理内存 ?如何利用 CleanMyMac X 进行系统清理

macbookair怎么清理内存 清理MacBook Air的内存可以通过以下几种方法&#xff1a; 优化储存空间。在MacBook Air上&#xff0c;可以通过“优化储存空间”来释放空间。这包括将文件储存在iCloud中&#xff0c;如桌面、文稿和iCloud信息&#xff0c;以及自动移除在iCloud中观看…

QT时间日期与定时器

时间日期与定时器 QTime: 时间数据类型&#xff0c;仅表示时间&#xff0c;如 15&#xff1a;23&#xff1a;13 QDate: 日期数据类型&#xff0c;仅表示日期&#xff0c;如 2017-4-5 QDateTime: 表示日期时间 如 2017-03-23 08&#xff1a;12&#xff1a;43 【示例】&#xf…

CSP-202203-1-未初始化警告

CSP-202203-1-未初始化警告 难点&#xff1a;时间复杂度 【核心】&#xff1a;统计输入的k组“赋值”中&#xff0c;右值不为0且未在先前作为左值出现过的次数【坑!】本题直接通过暴力枚举时间复杂度很可能过不了 【90分思路】 定义数组 initialized 用来存储已经处理过的左…

从中序与后序遍历序列构造二叉树

给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], postorder [9,15,7,20,3] 输出&#xff1a;[3…

深入了解RocketMQ消息中间件:架构、特性和应用场景

深入了解RocketMQ消息中间件&#xff1a;架构、特性和应用场景 引言 在当今的软件开发和系统架构中&#xff0c;消息中间件扮演着至关重要的角色。随着系统复杂度的增加和业务需求的变化&#xff0c;传统的直接接口调用已经无法满足大规模分布式系统的通信需求。消息中间件作为…

Flink CDC 与 Kafka 集成:Snapshot 还是 Changelog?Upsert Kafka 还是 Kafka?

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维…

MySQL-SQL优化

文章目录 1. SQL性能分析1.1 SQL执行频率1.2 慢查询日志1.3 profile详情1.4 explain 2. SQL优化2.1 Insert 优化2.2 Group By 优化2.3 Order By 优化2.4 Limit 优化2.5 Count() 优化2.6 Update 优化 3. 拓展3.1 请你说一下MySQL中的性能调优的方法&#xff1f;3.2 执行 SQL 响应…

堆的概念实现

前言 本文将详细讲解堆。堆是一种二叉树&#xff08;一般是完全二叉树&#xff09;使用顺序结构的数组来存储。 tip&#xff1a;这里我们需要注意区分堆在不同地方的含义&#xff0c;这里的堆是一个数据结构&#xff0c;操作系统虚拟进程地址空间的堆是操作系统中管理内存的一块…

kubernetes镜像仓库harbor

一、镜像仓库的种类 GitHub GitHub有付费版和免费版,目前默认的docker镜像拉取策略是从GitHub上进行拉取gitee 国内harbor私有仓库二、harbor仓库规划设计 私有镜像仓库 Harbor 安装和配置 新创建一台虚拟机安装harbor, 配置如下: 主机名ip配置网络harbor192.168.1.204VCPU/…

【04】C++ 类和对象 3

文章目录 &#x1f308; Ⅰ const 修饰 this 指针&#x1f308; Ⅱ static 静态成员&#x1f308; Ⅲ friend 友元1. 友元函数2. 友元类 &#x1f308; Ⅳ 内部类&#x1f308; Ⅴ 匿名对象 &#x1f308; Ⅰ const 修饰 this 指针 1. const 成员函数概念 将 const 修饰的 成…

云卷云舒:谈云数据库的备份容灾

备份和容灾是云数据库的标配&#xff0c;是实现数据恢复、保护的关键。 一、数据库备份原理和策略 &#xff08;1&#xff09;灾备方案设计&#xff1a;根据业务需求和数据的重要性&#xff0c;对不同级别业务数据库采用定制的备份策略&#xff0c;并且把备份存储在不同的AZ或…

「深度学习」长短时记忆网络LSTM

一、经典模型 \widetilde{c}^{<t>} tanh(w_{c}[a^{<t-1>},x^{<t>}]b_{c}) 更新门&#xff1a;\Gamma_{u} \sigma(w_{u}[a^{<t-1>},x^{<t>}]b_{u}) 遗忘门&#xff1a;\Gamma_{f} \sigma(w_{f}[a^{<t-1>},x^{<t>}]b_{f}) 输出门…