当前位置: 首页 > article >正文

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 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.kler.cn/a/154264.html

相关文章:

  • 大语言模型通用能力排行榜(2024年11月8日更新)
  • uniapp 跨域前端代理
  • 计算机组成原理笔记----基础篇
  • java常用工具包介绍
  • 类与对象;
  • [ACTF2020]Upload 1--详细解析
  • conda环境下numpy模块ValueError: setting an array element with a sequence.问题解决
  • 计算机 Wi-Fi 掉线后重新连接并恢复网络访问(GPT4)
  • 修改apt-get的出口IP
  • 一篇带你串通数据结构
  • node的proxy-server使用
  • 【力扣1929】数组串联
  • Android 13 - Media框架(15)- OpenMax(三)
  • 微前端qiankun示例 Umi3.5
  • matlab 汽车单车模型固定点跟踪算法
  • io基础入门
  • CPU 使用率和负载Load
  • golang Pool实战与底层实现
  • k8s(三): 基本概念-ReplicaSet与Deployment
  • TA-Lib学习研究笔记——Price Transform (五)
  • 阿里千问Qwen-72 b在中文测试中击败了GPT-3.5
  • 【Matlab】如何快速入门一项新技能-以Matlab/Simulink入门为例
  • C语言中的格式化输出符号:%d %c %p %x等
  • 750mA Linear Charger with Power Path Management
  • Windows安装Mysql Workbench及常用操作
  • vscode一直不能跳转函数定义或者别的定义c_cpp_properties.json、settings.json