2023.11.30 关于 MyBatis 动态 SQL 的使用

news2024/12/27 19:27:28

目录

引言

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 user
        where 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
@Test
    void 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 user
        where 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 = 0
        where 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.coloradmin.cn/o/1277468.html

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

相关文章

canvas 凸包效果

前言 微信公众号&#xff1a;前端不只是切图 代码运行的最终效果在文章最后 什么是凸包 本篇文章主要阐述如何在canvas上实现凸包的效果&#xff0c;我们先来看看下什么是凸包&#xff0c;先上附图 从上面的图可以看出&#xff0c;图中的内容包含点p0-点p12&#xff0c;而红框部…

企业网盘在医疗行业资料管理中的应用与优势

随着企业网盘的广泛应用&#xff0c;医疗行业正逐渐实现资料安全存储和智能化管理。海量应用的推动下&#xff0c;医院管理正朝着线上化、智能化发展迈进。然而&#xff0c;医疗行业仍面临着诸多挑战。 医疗行业的痛点在于病例、档案、药品资料繁多且保存周期长。这些资料的整理…

读书笔记:《Effective Modern C++(C++14)》

Effective Modern C&#xff08;C14&#xff09; GitHub - CnTransGroup/EffectiveModernCppChinese: 《Effective Modern C》- 完成翻译 Deducing Types 模版类型推导&#xff1a; 引用&#xff0c;const&#xff0c;volatile被忽略数组名和函数名退化为指针通用引用&#…

抓取检测(Grasp Dection)

抓取检测 抓取检测被定义为能够识别任何给定图像中物体的抓取点或抓取姿势。抓取策略应确保对新物体的稳定性、任务兼容性和适应性&#xff0c;抓取质量可通过物体上接触点的位置和手的配置来测量。为了掌握一个新的对象&#xff0c;完成以下任务&#xff0c;有分析方法和经验…

第二十二章 指定元素和属性的命名空间 - 指定被视为Global元素的对象的命名空间

文章目录 第二十二章 指定元素和属性的命名空间 - 指定被视为Global元素的对象的命名空间指定被视为Global元素的对象的命名空间指定映射为元素的属性的命名空间案例1&#xff1a;属性被视为本地元素案例2:属性被视为Global元素 第二十二章 指定元素和属性的命名空间 - 指定被视…

以热爱的态度对待生活,就是最自己的温柔

粉色系拼接款羽绒服 90白鸭绒&#xff0b;连帽立领设计 防风又保暖&#xff0c;柔软蓬松舒适感十足 衣服上加了时尚的字母印花元素 袖口做了魔术贴设计 下摆也做了可调节抽绳 防风保暖五部做到实处哦 宽松版型&#xff0c;很耐穿保暖性又很强 简单大方&#xff0c;搭配…

Filebeat使用指南

Filebeat介绍主要优势主要功能配置日志的解析Kibana中设置日志解析安装步骤安装Filebeat安装监控通过prometheus监控 Filebeat和Logstash的主要区别 Filebeat介绍 Filebeat是使用Golang实现的轻量型日志采集器&#xff0c;也是Elasticsearch stack的一员。它可以作为一个agent…

自定义Vue的DockPanel-Layout

创作来源 1、在vue项目中需要有停靠、浮动、面板布局等需求&#xff0c;如arcgis的界面布局 2、在npm中搜索了关于vue的docklayout组件&#xff0c;搜索后就一个组件imengyu/vue-dock-layout&#xff0c;截图如下&#xff0c;该组件没有停靠组件&#xff0c;没有浮动组件&…

python etree.HTML 以及xpath 解析网页的工具

文章目录 导入模块相关语法实战 导入模块 from lxml import etree相关语法 XPath&#xff08;XML Path Language&#xff09;是一种用于在XML文档中定位和选择元素的语言。XPath的主要应用领域是在XML文档中进行导航和查询&#xff0c;通常用于在XML中选择节点或节点集合。以…

C++模版

文章目录 C模版1、泛型编程2、函数模版2.1、函数模版概念2.2、函数模版格式2.3、函数模版原理2.4、函数模版的实例化2.5、模板参数的匹配原则 3、类模版3.1、类模版概念3.2、类模版格式3.3、类模板的实例化 C模版 1、泛型编程 泛型编程&#xff08;Generic Programming&#x…

华清远见嵌入式学习——C++——作业4

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;class Stu {friend const Stu operator*(const Stu &L,const Stu &R);friend bool operator<(const Stu &L,const Stu &R);friend Stu operator-(Stu &L,const S…

2022年高校大数据挑战赛A题工业机械设备故障预测求解全过程论文及程序

2022年高校大数据挑战赛 A题 工业机械设备故障预测 原题再现&#xff1a; 制造业是国民经济的主体&#xff0c;近十年来&#xff0c;嫦娥探月、祝融探火、北斗组网&#xff0c;一大批重大标志性创新成果引领中国制造业不断攀上新高度。作为制造业的核心&#xff0c;机械设备在…

KEPserver和S7-200SMART PLC通信配置

KEPserver和S7-1200PLC通信配置,请查看下面文章链接: https://rxxw-control.blog.csdn.net/article/details/134683670https://rxxw-control.blog.csdn.net/article/details/134683670 1、OPC通信应用 2、选择Siemens驱动 3、添加S7-200设备

百度/抖音/小红书/微信搜索品牌形象优化怎么做?

搜索口碑是网络营销不可或缺的一部分&#xff0c;企业如何做好品牌搜索口碑优化呢&#xff1f;小马识途营销顾问建议从以下几方面入手。 1. 通过关键字优化提高自身知名度 通过对竞争对手和目标客户的关键字进行分析&#xff0c;企业可以确定哪些关键字可以提高自身品牌知名度。…

数据结构与算法-静态查找表

&#x1f31e; “清醒 自律 知进退&#xff01;” 查找 &#x1f388;1.查找的相关概念&#x1f388;2.静态查找表&#x1f52d;2.1静态查找表的类定义&#x1f52d;2.2顺序查找&#x1f52d;2.3二分查找&#x1f50e;二分查找例题 &#x1f52d;2.4分块查找&#x1f52d;2.5三…

SQL面试题,判断if的实战应用

有如下表&#xff0c;请对这张表显示那些学生的成绩为及格&#xff0c;那些为不及格 1、创建表&#xff0c;插入数据 CREATE TABLE chapter8 (id VARCHAR(255) NULL,name VARCHAR(255) NULL,class VARCHAR(255) NULL,score VARCHAR(255) NULL );INSERT INTO chapter8 (id, n…

非应届生简历模板13篇

无论您是职场新人还是转行求职者&#xff0c;一份出色的简历都是获得心仪岗位的关键。本文为大家精选了13篇专业的非应届生简历模板&#xff0c;无论您的经验如何&#xff0c;都可以灵活参考借鉴&#xff0c;提升自己的简历质量。让简历脱颖而出&#xff0c;轻松斩获心仪职位&a…

02数仓平台Zookeeper

概述 ZooKeeper是一种分布式协调服务&#xff0c;用于管理大型主机集。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper通过其简单的架构和API解决了这个问题。ZooKeeper允许开发人员专注于核心应用程序逻辑&#xff0c;而不必担心应用程序的分布式性质。 Zookeepe…

Dart编程基础 - 一种新的编程语言

Dart编程基础 – 一种新的编程语言 Dart Programming Essentials - A New Type of Programming Language By JacksonML Dart is a client-optimized language for fast apps on any platform From dart.dev 在1999年之前&#xff0c;和我一样对计算机技术感兴趣的伙伴们&…

高级算法设计与分析练习1-10

文章目录 7-1 锦标赛7-2 选我啊&#xff01;7-3 朋友圈7-4 最短路径7-5 ICPC保定站7-6 填数字7-7 Werewolf7-8 球队“食物链”7-9 代码排版7-10 至多删三个字符 7-1 锦标赛 HBU有2 n名ACM选手&#xff0c;编号依次为1−2 n。他们现在要进行一场程序设计比赛&#xff0c;这个比…