Mybatis高级(动态SQL)
目录
一、动态SQL
1.1 数据准备:
1.2 <if>标签
1.3<trim> 标签
1.4<where>标签
1.5<set>标签
1.6 <foreach>标签
1.7<include> 标签
一、动态SQL
动态SQL是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的sql拼接
在注册用户的时候,可能会有这样⼀个问题,如下图所示:
修改个人信息时会有两种字段:必填字段和非必填字段,那如果在添加用户的时候有不确定的字段传入。这个时候就需要使用动态标签来判断了,比如添加的时候性别gender为非必填字段,具体实现如下:
1.1 数据准备:
UserInfo类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}
user_info表:
-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;-- 使⽤数据数据
USE mybatis_test;-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS user_info;
CREATE TABLE `user_info`
(`id` INT(11) NOT NULL AUTO_INCREMENT,`username` VARCHAR(127) NOT NULL,`password` VARCHAR(127) NOT NULL,`age` TINYINT(4) NOT NULL,`gender` TINYINT(4) DEFAULT '0' COMMENT '1男2⼥0默认',`phone` VARCHAR(15) DEFAULT NULL,`delete_flag` TINYINT(4) DEFAULT 0 COMMENT '0正常, 1删除',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),PRIMARY KEY (`id`)
) ENGINE = INNODBDEFAULT CHARSET = utf8mb4;-- 添加用户信息
INSERT INTO mybatis_test.user_info(username, `password`, age, gender, phone)
VALUES ('admin', 'admin', 18, 1, '18612340001');
INSERT INTO mybatis_test.user_info(username, `password`, age, gender, phone)
VALUES ('zhangsan', 'zhangsan', 18, 1, '18612340002');
INSERT INTO mybatis_test.user_info(username, `password`, age, gender, phone)
VALUES ('lisi', 'lisi', 18, 1, '18612340003');
INSERT INTO mybatis_test.user_info(username, `password`, age, gender, phone)
VALUES ('wangwu', 'wangwu', 18, 1, '18612340004');
article_info表:
-- 创建⽂章表
DROP TABLE IF EXISTS article_info;CREATE TABLE articleinfo
(id INT PRIMARY KEY auto_increment,title VARCHAR(100) NOT NULL,content TEXT NOT NULL,uid INT NOT NULL,delete_flag TINYINT(4) DEFAULT 0 COMMENT 'O - 正常,1 - 删除',create_time DATETIME DEFAULT now(),update_time DATETIME DEFAULT now()
) DEFAULT charset 'utf8mb4';# 插入数据
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正⽂', 1 );
INSERT INTO article_info ( title, content, uid ) VALUES ( 'Python', 'Python正⽂', 2 );
INSERT INTO article_info ( title, content, uid ) VALUES ( 'MySQL', 'MySQL正⽂', 1);
在数据库中查询数据:
user_info表:
article_info表:
1.2 <if> 标签
Mapper接口:
Integer insertUserByCondition(UserInfo userInfo);
Mapper.xml实现:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/ /DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.book.mapper.UserInfoMapper"><insert id="insertUserByCondition">INSERT INTO user_info (username,`password`,age,<if test="gender != null">gender,</if>phone)VALUES (#{username},#{age},<if test="gender != null">#{gender},</if>#{phone})</insert></mapper>
测试:
1、设置gender不为空
@Testvoid insertUserByCondition() {log.info("添加用户信息");UserInfo userInfo = new UserInfo();userInfo.setUsername("小王");userInfo.setPassword("123456");userInfo.setAge(18);userInfo.setGender(1);userInfo.setPhone("12345678901");userInfoMapper.insertUserByCondition(userInfo);log.info("添加成功!");}
测试结果:
2、设置gender为空
@Testvoid insertUserByCondition() {log.info("添加用户信息");UserInfo userInfo = new UserInfo();userInfo.setUsername("小王");userInfo.setPassword("123456");userInfo.setAge(18);
// userInfo.setGender(1);userInfo.setPhone("12345678901");userInfoMapper.insertUserByCondition(userInfo);log.info("添加成功!");}
测试结果:
1.3 <trim>标签
之前的插入用户功能,只是有一个gender字段可能是选填项,如果有多个字段,一般考虑使用标签结合标签,对多个字段都采取动态生成的方式。
标签中有如下属性:
prefix | 表示整个语句块,以prefix的值作为前缀 |
suffix | 表示整个语句块,以suffix的值作为后缀 |
prefixOverrides | 表示整个语句块要去除掉的前缀 |
suffixOverrides | 表示整个语句块要去除掉的后缀 |
调整Mapper.xml的插入语句为:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/ /DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.book.mapper.UserInfoMapper"><insert id="insertUserByCondition">INSERT INTO user_info<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></mapper>
测试:
运行结果:
在以上sql动态解析时,会将第一个部分做如下处理:
·基于prefix配置,开始部分加上(
·基于suffix配置,结束部分加上)
·多个组织的语句都以,结尾,在最后拼接好的字符串还会以,结尾,会基于suffixOverrides配置去掉最后一个,
1.4<where>标签
当我们查询不同电脑时,系统会根据我们的筛选条件,动态组装where条件
实现:
接口定义:
List<UserInfo> queryByCondition(Integer age, Integer gender, Integer deleteFlag);
Mapper.xml实现:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/ /DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.book.mapper.UserInfoMapper"><select id="queryByCondition" resultType="com.example.book.model.UserInfo">select id, username, age, gender, phone, delete_flag, create_time,update_timefrom user_info<where><if test="age != null">and age = #{age}</if><if test="gender != null">and gender = #{gender}</if><if test="deleteFlag != null">and delete_flag = #{deleteFlag}</if></where></select></mapper>
测试:
测试结果:
只会在子元素有内容的情况下才插入where子句,而且会自动去除子句的开头的AND或 OR
1.5<set>标签
需求:根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容.
接口定义:根据传入的用户id属性,修改其他不为null的属性
Mapper接口:
Integer updateUserByCondition(UserInfo userInfo);
Mapper.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/ /DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.book.mapper.UserInfoMapper"><update id="updateUserByCondition">update user_info<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></mapper>
<set>:动态的在SQL语句中插入set关键字,并会删掉额外的逗号.(用于update语句中)
测试:
@Testvoid updateUserByCondition() {UserInfo userInfo = new UserInfo();userInfo.setId(12);userInfo.setUsername("小张");userInfo.setAge(22);userInfo.setDeleteFlag(1);userInfoMapper.updateUserByCondition(userInfo);}
测试结果:
1.6 <foreach>标签
对集合进行遍历时可以使用该标签。标签有如下属性
collection | 定方法参数中的集合,如List,Set,Map或数组对象 |
item | 便历时的每一个对象 |
open | 语句块开头的字符串 |
close | 语句块结束的字符串 |
separator | 每次遍历之间间隔的字符串 |
需求:根据多个userid,删除用户数据
Mapper接口:
void deleteByIds(List<Integer> ids);
ArticleMapper.xml 中新增删除sql:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org/ /DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.book.mapper.ArticleInfoMapper"><delete id="deleteByIds">delete from article_infowhere id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete></mapper>
测试:
@Testvoid testDeleteByIds() {articleInfoMapper.deleteByIds(List.of(2,3));}
运行结果:
1.7 <include> 标签
在xmI映射文件中配置的SQL,有时可能会存在很多重复的片段,此时就会存在很多余的代码
我们可以对重复的代码片段进行抽取,将其通过<sql>标签封装到一个SQL片段,然后再通过
<include>标签进行引用。
<sql>:定义可重用的SQL片段
<include>:通过属性refid,指定包含的SQL片段
<sql id="allColumn">id, username, age, gender, phone, delete_flag, create_time, update_time</sql>
通过标签在原来抽取的地方进行引用。操作如下:
<select id="queryAllUser" resultMap="BaseMap">select<include refid="allColumn"></include>from user_info</select><select id="queryById" resultType="com.example.demo.model.UserInfo">select<include refid="allColumn"></include>from userinfo where id= #{id}</select>
相关文章:

Mybatis高级(动态SQL)
目录 一、动态SQL 1.1 数据准备: 1.2 <if>标签 1.3<trim> 标签 1.4<where>标签 1.5<set>标签 1.6 <foreach>标签 1.7<include> 标签 一、动态SQL 动态SQL是Mybatis的强⼤特性之⼀,能够完成不同条件下不同…...
申论对策建议类【2022江苏B卷第一题“如何开展网络直播”】
材料: 近年来,公安交管部门通过网络直播,将执法过程和执法细节以视频形式呈现在公众面前,吸引“围观”、组织点评,让执法过程变成一堂生动的法治公开课。 “各位网友,大家好!这里是‘全国交通…...

蓝耘智算携手DeepSeek,共创AI未来
🌟 各位看官号,我是egoist2023! 🌍 种一棵树最好是十年前,其次是现在! 🚀 今天来学习如何通过蓝耘智算使用DeepSeek R1模型 👍 如果觉得这篇文章有帮助,欢迎您一键三连&a…...
FFmpeg源码:url_find_protocol函数分析
一、url_find_protocol函数的定义 url_find_protocol函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的源文件libavformat/avio.c中: static const struct URLProtocol *url_find_protocol(const char *filename) {const URLProt…...
3D与2D机器视觉机械臂引导的区别
3D与2D机器视觉在机械臂引导中的主要区别如下: 数据维度 2D视觉:仅处理平面图像,提供X、Y坐标信息,无法获取深度(Z轴)数据。 3D视觉:处理三维空间数据,提供X、Y、Z坐标及物体的姿态…...

C# 添加图标
一、前言 为应用程序添加图标是优化用户界面、提升应用辨识度的重要操作。合适的图标能帮助用户快速识别和区分不同应用,增强应用的易用性和专业性。 本指南旨在为你提供详细、易懂的步骤,教你如何为应用程序的窗体添加图标。从图标素材的获取到具体的…...

基于 Python 和 Django 的北极星招聘数据可视化系统(附源码,部署)
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
基于STM32、HAL库、MB85RC16PNF(I2C接口)驱动程序设计
一、概述: MB85RC16PNF 是富士通推出的16Kbit(2K x 8位)FRAM(铁电随机存取存储器),具有非易失性、高读写速度和低功耗特性,常用于数据存储。 二、硬件连接: MB85RC16PNF通过I2C接口与STM32L4XX通信,典型连接如下: VDD:3.3V VSS:GND SDA:I2C数据线 SCL:I2C时钟线…...

【产品推介】可驱动5A负载的降压型DC/DC转换器XBL1663
一、产品简介 采用ESOP-8封装的XBL1663最大可输出5A电流 芯伯乐XBL1663是一款专为降压型DC/DC转换器设计的单片集成电路,具有高转换效率、恒定开关频率工作的特点。内置功率 MOSFET可在 4.5 V-40V 输入电源上实现 5A 峰值输出电流,并具有出色的负载和线…...

20.【线性代数】——坐标系中,平行四边形面积=矩阵的行列式
三 坐标系中,平行四边形面积矩阵的行列式 定理验证 定理 在坐标系中,由向量(a,b)和向量(c,d)组成平行四边形的面积 矩阵 [ a b c d ] \begin{bmatrix} a&b\\ c&d \end{bmatrix} [acbd]的行列式,即&#x…...
数据库知识速记:事物隔离级别
数据库知识速记:事物隔离级别 一、什么是事物隔离级别? 事物隔离级别(Transaction Isolation Levels)指的是在数据库管理系统中,不同事物之间在访问共享数据时的隔离程度。隔离级别不仅影响数据的读取和写入行为&…...

重构测试项目为spring+springMVC+Mybatis框架
重构测试项目为springspringMVCMybatis框架 背景 继上次将自动化测试时的医药管理信息系统项目用idea运行成功后,由于项目结构有些乱,一部分代码好像也重复,于是打算重新重构以下该项目,这次先使用springspringMVCMybatis框架 …...
如何使用OPENAI的Whisper功能进行音频字母提取功能
首先你可以使用 Python 中的 requests 库来下载该音频文件,然后通过 open() 打开该文件并传递给 OpenAI Whisper API。 完整代码如下: 安装需要的库: pip install openai requests Python 代码: OPENAI_API_KEY "your o…...

DFS算法篇:理解递归,熟悉递归,成为递归
1.DFS原理 那么dfs就是大家熟知的一个深度优先搜索,那么听起来很高大尚的一个名字,但是实际上dfs的本质就是一个递归,而且是一个带路径的递归,那么递归大家一定很熟悉了,大学c语言课程里面就介绍过递归,我…...
2025java常见面试题第一弹
1. Java中的HashMap和Hashtable有什么区别? 答案: 线程安全性: HashMap是线程不安全的,适合单线程环境。如果在多线程环境下使用,可能会出现数据不一致的问题。 Hashtable是线程安全的,内部方法通过synch…...

JMeter工具介绍、元件和组件的介绍
Jmeter功能概要 JDK常用文件目录介绍 Bin目录:存放可执行文件和配置文件 Docs目录:是Jmeter的API文档,用于开发扩展组件 printable_docs目录:用户帮助手册 lib目录:存放JMeter依赖的jar包和用户扩展所依赖的Jar包…...

机舱卫生和空气质量改善
公共卫生挑战:在密闭空间内控制病原体 由于公共交通等密闭空间内的人员密度很高,因此保持良好的空气质量至关重要。有效的通风系统在循环新鲜空气和降低空气中病原体和污染物的浓度方面起着关键作用。使用高效微粒空气 (HEPA) 过滤…...

springBoot之环境变量
springboot 在new SpringBootApplication()时, 会扫描所有的spring.factory; 它会给每个接口当做group,所有实现类为List当做value,形成map; group -> List 系统属性 java的相关属性 系统环境属性,指的是操作系统相关的配置 每个配置对应一个contro…...
萨班斯-奥克斯利法案(Sarbanes-Oxley Act, SOX):公司财务透明度的守护者(中英双语)
萨班斯-奥克斯利法案(Sarbanes-Oxley Act):公司财务透明度的守护者 在2001年安然(Enron)和世通(WorldCom)等公司财务造假丑闻爆发后,美国政府迅速出台了《萨班斯-奥克斯利法案》&am…...
iOS 中使用 FFmpeg 的高级功能 - 滤镜(Filters)
FFmpeg 提供了强大的滤镜功能,可以对音视频进行各种处理,例如裁剪、缩放、添加水印、调整颜色、添加特效等。 1. FFmpeg 滤镜基础知识 1.1 什么是滤镜(Filters)? 滤镜是 FFmpeg 提供的一种功能,用于对音视频流进行处理。滤镜链(Filter Chain)是多个滤镜的组合,按顺序…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...