2023.11.30 关于 MyBatis 动态 SQL 的使用

目录

引言

if 标签 

trim 标签 

where 标签 

set 标签 

foreach 标签 


引言

  • 动态 sql 是 MyBatis 的强大特性之一
  • 允许你根据输入的参数动态地构建 sql 语句
  • 从而在运行时根据不同的条件生成不同的 sql

核心思想

  • 基于提供的数据和条件,能够修改、增加、删除 sql 语句的部分内容
  • 这为编写更通用、可重用的 sql 提供了极大的灵活性

  • 以下我们介绍 5 个常用的动态 sql 标签

if 标签 

实例理解

  • 此处我们想要实现 根据 name 和 age 字段来筛选用户信息 功能

创建数据库

  • 在数据库中创建一个如下图所示的 user 表,并插入几条用户数据
  • 注意这里的 state 状态
  • 值为 1 表示该用户可正常登录
  • 值为 0 表示该用户异常,无法登录


实现 UserMapper 接口

  • 此处我们实现一个 selectUser 方法
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;//添加 @Mapper 注解 代表该接口会伴随这 项目的启动而注入到容器中
@Mapper
public interface UserMapper {//    根据 name 和 age 字段来筛选用户信息List<User> selectUser(@Param("user_name") String name,@Param("user_age") Integer age);
}

实现 UserMapper XML 文件

  • 在与接口相对应的 XML 文件中
  • 添加上与 selectUser 方法 相对应的 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.demo.mapper.UserMapper"><select id="selectUser" resultType="com.example.demo.entity.User">select * from userwhere 1=1<if test="user_name != null">and name = #{user_name}</if><if test="user_age != null">and age = #{user_age}</if></select></mapper>

分析功能 与 select 语句

  • 根据 name 和 age 字段筛选用户信息    存在四种情况

情况一:

  • name 和 age 均不为空,其所对应的 sql 语句为:
select * from user where name = #{user_name} and age = #{user_age}

情况二:

  • name 和 age 均为空,其所对应的 sql 语句为:
select * from user

情况三:

  • name 为空, age 不为空,其所对应的 sql 语句为:
select * from user where age = #{user_age}

情况四:

  • name 不为空, age 为空,其所对应的 sql 语句为:
select * from user where name = #{user_name}

分析 XML 中的 select 语句 

  • 加上 if 标签后,该 sql 也将存在四种情况,与上述分析的四种情况相对应

注意:

  • 理解此处加上的 绿框部分,即 '1=1'
  • 如果删除绿框部分,那么我们再观察下图

  • 所以 XML 中的 select 语句必须加上绿框部分,否则将会导致 sql 语法错误

创建 selectUser 的测试方法

  • 我们随意选择上述四种情况的任意一种进行传参
  • 此处我们选择仅传参 age= 20
@Testvoid selectUser() {List<User> users = userMapper.selectUser(null,20);users.stream().forEach(System.out::println);}

执行测试方法

  • 测试方法成功执行

trim 标签 

属性

  • prefix:表示整个语句块,以 prefix 的值作为前缀
  • suffix:表示整个语句块,以 suffix 的值作为后缀
  • prefixOverrides:表示整个语句块,所需要去除的多余前缀
  • suffixOverrides:表示整个语句块,所需要去除的多余后缀

实例理解

  • 下方的 select 查询语句为了保证 sql 语法的正确性,还必须得添加上 '1=1' 
<select id="selectUser" resultType="com.example.demo.entity.User">select * from userwhere 1=1<if test="user_name != null">and name = #{user_name}</if><if test="user_age != null">and age = #{user_age}</if></select>
  • 但是我们可以使用 <trim> 标签来改写上方的 select 语句,使其可以不用添加上 '1=1'的同时保障 sql 语法的正确性
select * from user<trim prefix="where" suffixOverrides="and"><if test="user_name != null">name = #{user_name} and</if><if test="user_age != null">age =#{user_age}</if></trim>

分析该 sql 语句

  • 此处经存在一种情况会 发生去除多余后缀 'and' 


注意:

  • 当 <trim> 标签中生成了代码那么才会添加 <trim> 标签里的前缀和后缀
  • 如果 <trim> 标签中未生成代码,则前缀和后缀都会省略

where 标签 

实例理解

  • 我们同样可以使用 <wehre> 标签来改写上述 根据 name 和 age 字段来筛选用户信息 的 sql 语句
<select id="selectUser" resultType="com.example.demo.entity.User">select * from user<where><if test="user_name != null">name = #{user_name}</if><if test="user_age != null">and age =#{user_age}</if></where>
</select>

注意:

  • 上述实例为 <where> 标签的正确写法不能写成下述 sql 语句
<select id="selectUser" resultType="com.example.demo.entity.User">select * from user<where><if test="user_name != null">name = #{user_name} and</if><if test="user_age != null">age =#{user_age}</if></where>
</select>
  • 因为 <where> 标签会帮去除最前面的多余 'and' 关键字 ,而不会帮去除最后面的多余 'and' 关键字
  • 即 <where> 标签相当于 <trim prefix="where" prefixOverrides = "and">

set 标签 

实例理解

  • 此处我们想实现一个 根据用户 id 修改用户各属性 功能

准备数据库

  • 在数据库中准备好一个 user 表


 实现 UserMapper 接口

  • 此处我们实现一个 updateById 方法
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;//添加 @Mapper 注解 代表该接口会伴随这 项目的启动而注入到容器中
@Mapper
public interface UserMapper {
//    根据 id 修改用户信息Integer updateById(User user);}

实现 UserMapper XML 文件

  • 在与接口相对应的 XML 文件中
  • 添加上与 updateById 方法 相对应的 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.demo.mapper.UserMapper"><update id="updateById" parameterType="com.example.demo.entity.User">update user<set><if test="name != null">name = #{name},</if><if test="age != 0">age = #{age},</if><if test="password != null">password = #{password},</if><if test="state != 0">state = #{state}</if></set>where id = #{id}</update></mapper>

创建 updateById 的测试方法

  • 此处我们修改 用户 id = 4 用户信息
  • 修改其姓名、年龄、密码,不修改其状态
@Test
void updateById() {User user = new User();user.setId(4);user.setName("haoran");user.setAge(20);user.setPassword("123123");int result = userMapper.updateById(user);System.out.println("updateById 方法 :" + (result == 1 ? "修改成功" : "修改失败"));
}

执行测试方法

  • 测试方法成功执行

  • 观察数据库中的 user 表


注意:

  • <set> 标签相当于 <trim prefix="set" suffixOverrides = ",">

foreach 标签 

属性

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

实例理解

  • 此处想实现一个 根据多个用户 Id 来批量封禁用户 功能

 准备数据库

  • 在数据库中准备好一个 user 表


 实现 UserMapper 接口

  • 此处我们实现一个 updateStateByIds 方法
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;//添加 @Mapper 注解 代表该接口会伴随这 项目的启动而注入到容器中
@Mapper
public interface UserMapper {
//    根据多个 id 批量封禁用户Integer updateStateByIds(@Param("user_ids") List<Integer> ids);
}

实现 UserMapper XML 文件

  • 在与接口相对应的 XML 文件中
  • 添加上与 updateStateByIds 方法 相对应的 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.demo.mapper.UserMapper"><update id="updateStateByIds">update user set state = 0where id in<foreach collection="user_ids" item="item" open="(" close=")" separator=",">#{item}</foreach></update></mapper>

创建 updateStateByIds 的测试方法

  • 此处我们封禁 id = 1、4、8、9  的用户
@Test
void updateStateByIds() {List<Integer> ids = new ArrayList<>();ids.add(1);ids.add(4);ids.add(8);ids.add(9);int result = userMapper.updateStateByIds(ids);System.out.println("updateById 方法 :" + (result > 1 ? "修改成功" : "修改失败"));
}

执行测试方法

  • 测试方法成功执行

  • 观察数据库中的 user 表

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

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

相关文章

css 输入框动态特效

先上图 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>css 输入框动效</title><style>.inputBox {position: relative;width: 250px;}.inputBox input {width: 100%;padding: 10px…

NodeJS(二):npm包管理工具、yarn、npx、pnpm工具等

目录 (一)npm包管理工具 1.了解npm 2.npm的配置文件 常见的配置属性 scripts属性*** 依赖的版本管理 3.npm安装包的细节 4.package-lock文件 5.npm install原理** 6.npm的其他命令 (二) 其他包管理工具 1.yarn工具 基本指令 2.cnpm工具 3.npx工具 (1)执行本地…

MVCC是什么

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

R语言手册30分钟上手

文章目录 1. 环境&安装1.1. rstudio保存工作空间 2. 创建数据集2.1. 数据集概念2.2. 向量、矩阵2.3. 数据框2.3.1. 创建数据框2.3.2. 创建新变量2.3.3. 变量的重编码2.3.4. 列重命名2.3.5. 缺失值2.3.6. 日期值2.3.7. 数据框排序2.3.8. 数据框合并(合并沪深300和中证500收盘…

Python-滑雪大冒险【附源码】

滑雪大冒险 《滑雪大冒险》是一款充满趣味性和挑战性的休闲竞技游戏&#xff0c;在游戏中&#xff0c;玩家将扮演一位勇敢的滑雪者&#xff0c;在雪山上展示他们的滑雪技巧&#xff0c;游戏采用2D图形界面&#xff0c;以第三人称视角呈现 运行效果&#xff1a;用方向键及方向键…

TCP/IP_整理起因

先分享一个初级的问题&#xff1b;有个客户现场&#xff0c;终端设备使用客户网络更新很慢&#xff0c;使用手机热点更新速度符合预期&#xff1b;网络部署情况如下&#xff1a; 前期花费了很大的精力进行问题排查对比&#xff0c;怀疑是客户网络问题&#xff08;其他的客户现…

Java网络编程——Java语言的反射机制

在Java运行环境中&#xff0c;对于任意一个类&#xff0c;能否知道这个类有哪些属性和方法&#xff1f;对于任意一个对象&#xff0c;能否调用它的任意一个方法&#xff1f;答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自Java语言的反射&#xff08;Refl…

vuepress-----18、图片缩放

图片引入两种方式 地址 # 图片缩放插件 # 实战 md文件引入图片 <img class"zoom-custom-imgs" :src"$withBase(/favicon.ico)" alt"favicon">安装配置插件 vuepress/medium-zoom: {selector: img.zoom-custom-imgs,},效果展示

Spring框架学习:Bean生命周期

目录 SpringBean的生命周期 Bean实例属性填充 三级缓存 常用的Aware接口 Spring IoC容器实例化Bean总结 SpringBean的生命周期 Spring Bean的生命周期是从 Bean 实例化之后&#xff0c;即通过反射创建出对象之后&#xff0c;到Bean成为一个完整对象&#xff0c;最终存储到…

Termux+Hexo结合内网穿透轻松实现安卓手机搭建博客网站发布公网访问

文章目录 前言 1.安装 Hexo2.安装cpolar3.远程访问4.固定公网地址 前言 Hexo 是一个用 Nodejs 编写的快速、简洁且高效的博客框架。Hexo 使用 Markdown 解析文章&#xff0c;在几秒内&#xff0c;即可利用靓丽的主题生成静态网页。 下面介绍在Termux中安装个人hexo博客并结合…

视频剪辑:视频转码实用技巧,批量将MP4转为MP3音频

随着数字媒体设备的普及&#xff0c;视频和音频文件已成为日常生活中的重要组成部分。有时&#xff0c;可能要将MP4视频文件转换为MP3音频文件&#xff0c;以提取其中的音频内容或者进行其他处理。这是耗费时间的任务&#xff0c;那要如何操作呢&#xff1f;本文详解云炫AI智剪…

一文理解什么是交叉熵损失函数以及它的作用

今天看一个在深度学习中很枯燥但很重要的概念——交叉熵损失函数。 作为一种损失函数&#xff0c;它的重要作用便是可以将“预测值”和“真实值(标签)”进行对比&#xff0c;从而输出 loss 值&#xff0c;直到 loss 值收敛&#xff0c;可以认为神经网络模型训练完成。 那么这…

进制 + 原码,反码,补码

进制转换 整数部分 小数部分 原码 反码 补码 原码转补码&#xff1a; 左边和右边第一个1不变&#xff0c;中间取反。-0 除外。 计算机系统中数值一律用补码来存储的原因 其他 术语 进制表 进制数的表示 详细教程可转 爱编程的大丙

SpringDataRedis 操作 Redis,并指定数据序列化器

文章目录 1. SpringDataRedis 概述2. 快速入门2.1 导入pom坐标2.2 配置文件2.3 测试代码2.4 数据序列化器2.5 StringRedisTemplate2.6 总结 1. SpringDataRedis 概述 SpringData 是Spring 中数据操作的模块&#xff0c;包含对各种数据库的集成&#xff0c;其中对Redis的集成模…

在pytorch中自定义dataset读取数据

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 有关我们数据读取预训练 以及如何将它打包成一个一个batch输入我们的网络的 首先我们来看一下之前我们在讲resnet网络时所使用的源码 我们去使用了官方实现的image folder去读取我们的图像数据 然…

html实现各种好看的鼠标滑过图片特效模板

文章目录 1.鼠标悬浮效果1.1 渐动效果1.2 渐变效果1.3 边框效果1.4 线行效果1.5 图标效果1.6 块状效果1.7 边线效果1.8 放大效果1.9 渐出效果1.10 痕迹效果1.11 交叉效果1.12 着重效果1.13 详展效果1.14 能动效果1.15 明细效果 2.主要源码2.1 源代码 源码下载 作者&#xff1a;…

linux后端基础---笔记整理(tmux、vim、shell、ssh/scp、git、thrift、docker)

目录 1.Linux常用文件管理命令 2.tmux终端复用器/vim命令式文本编辑器 3.Shell语法 3.1 Shell—版本3.2 新建一个test.sh文件3.3 Shell文件—运行方式3.4 Shell—注释3.5 Shell—变量3.6 Shell—默认变量&#xff0c;文件参数, “$”的用法3.7 Shell—数组3.8 shell—expr命令…

今日问题:解决最新Chrome和chromedriver版本对不上的问题

from selenium import webdriver #from .chrome.webdriver import WebDriver as Chrome from selenium.webdriver.common.by import By from time import sleep driver webdriver.Chrome()driver.get("https://www.baidu.com/") driver.maximize_window()#窗口最大化…

SpringBoot + Spring Cloud Alibaba + Nacos实现服务管理

1、参考文档 Spring Cloud Alibaba参考文档 https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/zh-cn/index.html Spring Cloud Alibaba官方文档 https://github.com/alibaba/spring-cloud-alibaba/wiki/ 2、引入 Alibaba 依赖 每个 SpringBoot 都有对应的…

[Firefly-Linux] RK3568 Ubuntu固件分区详解

RK为了方便开发与产品定制&#xff0c;自己定义了一套固件的分区&#xff0c;这些分区信息存放在parameter.txt文件中&#xff0c;Firefly参考这个文件定义了自己的Ubuntu分区&#xff0c;文件为parameter-ubuntu.txt&#xff0c;存放于Linux_SDK的device/rockchip/rk356x目录下…