【Spring 篇】深入探讨MyBatis映射文件中的动态SQL

在这里插入图片描述

MyBatis,这个名字在Java开发者的世界中犹如一道光芒,照亮着持久层操作的道路。而在MyBatis的映射文件中,动态SQL则是一个让人爱-hate的存在。有时候,你感叹它的灵活性,有时候,你可能会为它的繁琐而头痛。但别担心,我们将在本文中一起揭开动态SQL的神秘面纱,带你领略它的魅力。

背景

MyBatis的映射文件是定义SQL语句的地方,而动态SQL则是在这里展现威力的地方。为了更好地理解动态SQL,让我们先从MyBatis映射文件的基础开始。

映射文件基础

在MyBatis中,我们通过XML文件定义SQL语句,这些XML文件通常被称为映射文件。一个简单的映射文件示例如下:

<!-- UserMapper.xml --><mapper namespace="com.example.UserMapper"><!-- 查询所有用户 --><select id="selectAllUsers" resultType="User">SELECT * FROM users</select><!-- 根据用户ID查询用户 --><select id="selectUserById" resultType="User" parameterType="int">SELECT * FROM users WHERE id = #{id}</select><!-- 插入用户 --><insert id="insertUser" parameterType="User">INSERT INTO users (username, password) VALUES (#{username}, #{password})</insert><!-- 更新用户 --><update id="updateUser" parameterType="User">UPDATE users SET username = #{username}, password = #{password} WHERE id = #{id}</update><!-- 删除用户 --><delete id="deleteUser" parameterType="int">DELETE FROM users WHERE id = #{id}</delete></mapper>

在这个映射文件中,我们定义了查询所有用户、根据用户ID查询用户、插入用户、更新用户和删除用户的SQL语句。每个SQL语句都有一个唯一的id,指定了该语句在Java代码中的调用标识。resultType用于指定查询结果的类型,而parameterType用于指定传入参数的类型。

动态SQL的诞生

MyBatis早期版本中,静态SQL是唯一的选择。这意味着你必须在映射文件中写死所有的SQL语句,不管什么条件都一样。但是,随着项目的复杂性增加,开发者们迫切需要一种能够根据不同条件灵活生成SQL语句的机制。

这就是动态SQL的诞生原因。动态SQL允许我们在映射文件中使用一些特殊的标签,根据条件的不同动态生成SQL语句。这为我们提供了更大的灵活性,使得我们能够根据需要构建不同的SQL查询。

初识动态SQL

让我们从最简单的动态SQL标签开始,逐步深入了解它们的用法。

if标签

<if>标签是动态SQL中最常用的标签之一。它允许我们在SQL语句中包含条件判断,根据条件的真假来动态生成SQL语句的一部分。

考虑一个场景:我们要查询用户列表,但是有时候我们只想查询特定状态的用户。这时候,我们可以使用<if>标签来动态添加条件:

<!-- UserMapper.xml --><select id="selectUsersByStatus" resultType="User">SELECT * FROM users<where><if test="status != null">AND status = #{status}</if></where>
</select>

在这个例子中,<if>标签检查了参数status是否不为null。如果不为null,就会动态添加AND status = #{status}到SQL语句中。这样,我们就可以根据需要选择性地添加条件。

choose、when、otherwise标签

有时候我们需要在多个条件中选择一个执行,这时候就可以使用<choose><when><otherwise>标签组合起来使用。看一个例子:

<!-- UserMapper.xml --><select id="selectUsersWithCondition" resultType="User">SELECT * FROM users<where><choose><when test="status != null">AND status = #{status}</when><when test="username != null">AND username = #{username}</when><otherwise>AND age &gt; 18</otherwise></choose></where>
</select>

在这个例子中,<choose>标签下的<when>标签会按顺序检查条件,当第一个条件为真时,执行相应的SQL语句;如果所有条件都为假,就执行<otherwise>标签下的SQL语句。这样,我们可以根据不同的条件来构建不同的查询。

trim标签

<trim>标签提供了更灵活的文本处理能力。它通常用于处理SQL语句的前缀和后缀,使得我们可以根据条件来动态添加或删除这些部分。

考虑一个更新用户信息的场景,我们希望根据传入的参数动态更新用户的字段:

<!-- UserMapper.xml --><update id="updateUserDynamic" parameterType="User">UPDATE users<set><trim prefix="SET" suffixOverrides=","><if test="username != null">username = #{username},</if><if test="password != null">password = #{password},</if><if test="email!= null">email = #{email},</if></trim></set>WHERE id = #{id}
</update>

在这个例子中,<trim>标签被用于动态生成SET关键字后的更新语句。它的prefix属性指定了前缀,suffixOverrides属性指定了在所有子元素生成的文本中需要去除的后缀。这样,我们就能够根据传入的参数动态生成更新语句,只更新有值的字段。

foreach标签

<foreach>标签用于处理集合类型的参数,通常用于在SQL语句中遍历集合生成对应的语句块。例如,我们想要根据一组用户ID查询用户列表:

<!-- UserMapper.xml --><select id="selectUsersByIdList" resultType="User">SELECT * FROM usersWHERE id IN<foreach item="id" collection="idList" open="(" separator="," close=")">#{id}</foreach>
</select>

在这个例子中,<foreach>标签用于遍历名为idList的集合,生成类似于IN (1, 2, 3)的语句块。这样,我们可以根据传入的ID列表动态生成查询条件。

实战演练

为了更好地理解动态SQL的使用,让我们通过一个实际的例子来演示如何在映射文件中应用动态SQL。

假设我们有一个User实体类,包含了用户的ID、用户名、密码、邮箱和状态等信息。我们希望根据不同的查询条件,动态生成SQL语句。

首先,定义User实体类:

// User.javapublic class User {private Long id;private String username;private String password;private String email;private Integer status;// 省略 getter 和 setter 方法
}

接下来,我们定义一个UserMapper接口和对应的映射文件UserMapper.xml

// UserMapper.javapublic interface UserMapper {List<User> selectUsersByCondition(User user);// 省略其他方法
}
<!-- UserMapper.xml --><mapper namespace="com.example.UserMapper"><select id="selectUsersByCondition" resultType="User">SELECT * FROM users<where><if test="id != null">AND id = #{id}</if><if test="username != null">AND username = #{username}</if><if test="password != null">AND password = #{password}</if><if test="email != null">AND email = #{email}</if><if test="status != null">AND status = #{status}</if></where></select><!-- 其他方法省略 --></mapper>

在这个例子中,我们定义了一个selectUsersByCondition方法,接受一个User对象作为参数。在映射文件中,通过使用<where>标签和多个<if>标签,我们能够根据User对象的属性是否为null来动态生成查询条件。这样,我们就可以根据传入的条件选择性地查询用户列表。

小结

动态SQL是MyBatis中一个强大而灵活的特性,通过使用一系列的标签,我们能够根据不同的条件动态生成SQL语句,使得我们的数据库操作更加灵活和可扩展。在本文中,我们深入探讨了动态SQL的各种标签,包括<if><choose><trim><foreach>等,通过实际的例子演示了它们的用法。希望本文能够帮助你更好地理解和使用MyBatis中的动态SQL,让你在项目开发中更加游刃有余。如果你是MyBatis的初学者,相信你已经对动态SQL有了更清晰的认识,让它成为你数据库操作的得力助手。

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191

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

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

相关文章

windows 11安装VMware 17 ,VMware安装Ubuntu 20.4

一、下载安装激活VMware 17 下载与激活&#xff1a;Vmware 17 下载地址、最新激活码 2024 _ 注意&#xff1a;安装路径自己选择&#xff0c;路径中尽可能避免中文或空格 二、下载Ubuntu 镜像 下载镜像地址&#xff1a;清华大学开源软件镜像站 点开下载镜像地址&#xff0c;找…

中科星图——Sentinel-2_MSI_L2A数据集

数据名称&#xff1a; Sentinel-2_MSI_L2A 数据来源&#xff1a; Copernicus 时空范围&#xff1a; 2022年10月-2023年1月 空间范围&#xff1a; 全国 数据简介&#xff1a; 哨兵2号&#xff08;Sentinel-2&#xff09;卫星是高分辨率多光谱成像卫星&#xff0c;携带一…

分布式一致性算法---Raft初探

读Raft论文也有一段时间了&#xff0c;但是自己总是以目前并没有完全掌握为由拖着这篇博客。今天先以目前的理解程度&#xff08;做了6.824的lab2A和lab2B&#xff09;对这篇论文做一个初步总结&#xff0c;之后有了更深入的理解之后再进行迭代&#xff0c;关于本文有任何疑问欢…

苹果眼镜(Vision Pro)的开发者指南(3)-【3D UI SwiftUI和RealityKit】介绍

为了更深入地理解SwiftUI和RealityKit,建议你参加专注于SwiftUI场景类型的系列会议。这些会议将帮助你掌握如何在窗口、卷和空间中构建出色的用户界面。同时,了解Model 3D API将为你提供更多关于如何为应用添加深度和维度的知识。此外,通过学习RealityView渲染3D内容,你将能…

【Java数据结构 -- 队列:队列有关面试oj算法题】

队列、循环队列、用队列模拟栈、用栈模拟队列 1.队列1.1 什么是队列1.2 创建队列1.3 队列是否为空和获取队头元素 empty()peek()1.4 入队offer()1.5 出队&#xff08;头删&#xff09;poll() 2. 循环队列2.1 创建循环队列2.2 判断是否为空isEmpty()和满isFull()2.3 入队enQueue…

JAVA的面试题四

1.电商行业特点 &#xff08;1&#xff09;分布式&#xff1a; ①垂直拆分:根据功能模块进行拆分 ②水平拆分:根据业务层级进行拆分 &#xff08;2&#xff09;高并发&#xff1a; 用户单位时间内访问服务器数量,是电商行业中面临的主要问题 &#xff08;3&#xff09;集群&…

python数据分析——numpy基本用法

numpy数据类型 在NumPy中&#xff0c;有多种数据类型可用于表示数组的元素。以下是一些常见的NumPy数据类型&#xff1a; int - 整数类型&#xff0c;如int8、int16、int32、int64等。uint -无符号整数类型&#xff0c;如uint8、uint16、uint32、uint64等。float -浮点数类型…

PaddleNLP 如何打包成Windows环境可执行的exe?

当我们使用paddleNLP完成业务开发后&#xff0c;需要将PaddleNLP打包成在Windows操作系统上可执行的exe程序。操作流程&#xff1a; 1.环境准备&#xff1a; python环境&#xff1a;3.7.4 2.安装Pyinstaller pip install pyinstaller 3.目录结构&#xff0c;main.py为可执…

测试开发基础 | 计算机网络篇(二):物理层与数据链路层

【摘要】 计算机网络知识是自动化测试等技术基础&#xff0c;也是测试面试必考题目。霍格沃兹测试学院特别策划了本系列文章&#xff0c;将带大家一步步夯实计算机网络的基础知识。由于物理层知识在互联网软件研发工作中用到的并不多&#xff0c;所以可以仅做一个简单的了解。物…

jQuery语法知识(DOM操作)

一、class 属性: .addClass&#xff08;&#xff09;、.hasClass&#xff08;&#xff09;.removeClass&#xff08;&#xff09;、.toggleClass&#xff08;&#xff09; 二、DOM 插入并包裹现有内容 1、.wrap( wrappingElement): 在每个配的元素外层包上一个html元素。 …

Buildroot显示kernel logo

buildroot开机时DSI屏幕变成跟uart一样输出log&#xff0c;现在想显示logo 1、failed to show loader logo [ 2.467479] mmcblk1: p1 p2 p3 p4 p5 p6 p7 p8 p9 [ 2.468827] rockchip-drm display-subsystem: cant not find any loader display [ 2.468859] rockc…

Windows Service 2008 r2的安装

创建虚拟机–&#xff08;操作非常简单&#xff0c;跟着图片的数据下一步即可&#xff09; 选择自己要安装的虚拟机版本 在这里可以更改虚拟机存放的位置 这里的40个G并不会马上占用&#xff0c;当虚拟机里的东西到40个G的大小就不会再存储东西了 选择和自己虚拟…

春运倒计时,AR 引领铁路运输安全新风向

根据中国交通新闻网发布最新消息&#xff0c;今年春运全国跨区域人员流动量预计达 90 亿人次。 随着春运期间旅客数量不断创下新高&#xff0c;铁路运输面临着空前的挑战与压力。 图源&#xff1a;pixabay 聚焦铁路运输效率与旅客安全保障问题&#xff0c;本期行业趋势将探讨 …

51-16 FusionAD 用于自动驾驶预测与规划任务的多模态融合论文精读

今天要分享的是基于BEV的多模态、多任务、端到端自动驾驶模型FusionAD&#xff0c;其专注于自动驾驶预测和规划任务。这项工作首次发表于2023年8月2日&#xff0c;性能超越了2023 CVPR最佳论文UniAD模型。论文题目是FusionAD: Multi-modality Fusion for Prediction and Planni…

记录一些随机约束的控制方法

文章目录 前言一、内嵌约束控制二、控制rand变量是否随机三、选择随机控制的变量四、控制约束块是否随机五、约束的嵌套控制总结 前言 在运用UVM验证过程中&#xff0c;经常会用到大量的随机&#xff0c;这个时候我们需要控制随机约束的打开或者关闭&#xff0c;来实现不同模式…

linux显示系统内存使用情况--free命令

free 命令是Linux系统中用于显示系统内存使用情况的一个常用工具。通过该命令&#xff0c;用户可以轻松了解系统的内存分配、使用情况以及性能状况。本文将深入介绍free命令的各个方面&#xff0c;并提供详细的示例。 安装与基本用法 通常来说&#xff0c;free命令已经预装在大…

基于Python实现人脸识别相似度对比

目录 引言背景介绍目的和意义 人脸识别的原理人脸图像获取人脸检测与定位人脸特征提取相似度计算 基于Python的人脸相似度对比实现数据集准备人脸图像预处理特征提取相似度计算 引言 背景介绍 人脸识别技术是一种通过计算机对人脸图像进行分析和处理&#xff0c;从而实现自动识…

2023.1.17 关于 Redis 持久化 AOF 策略详解

目录 引言 AOF 策略 实例演示一 缓冲区 重写机制 手动触发 自动触发 AOF 重写流程 实例演示二 引言 Redis 实现持久化的两大策略 RDB ——> Redis DataBase&#xff08;定期备份&#xff09;AOF ——> Append Only File&#xff08;实时备份&#xff09; 注意&…

JavaEE:多线程(2):线程状态,线程安全

目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入 死锁 死锁的解决方法 Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪&#xff1a;线程随时可以去CPU上执行&#xff0c;也包含在CPU上执行的…

漏洞补丁修复之openssl版本从1.1.1q升级到1.1.1t以及python版本默认2.7.5升级到2.7.18新版本和Nginx版本升级到1.24.0

​ 一、Openssl升级 1、查看Openssl安装的版本 openssl version 2、查看Openssl路径 which openssl 3、上传openssl安装包到服务器:openssl-1.1.1t.tar.gz,并且解压,安装: mv /usr/local/openssl /usr/local/backup_openssl_1.1.1q_20240120 mkdir /usr/local/openssl tar…