【Spring Boot + MyBatis|第4篇】MyBatis 动态 SQL:if、where、foreach 使用详解

前言

前面我们已经学习了三层架构、参数接收和统一返回结果。接下来就要进入 MyBatis 中非常常用的一个知识点:动态 SQL。

在项目中,查询条件经常不是固定的。比如员工查询时,前端可能传姓名,也可能传性别,也可能两个都不传。如果我们给每一种情况都单独写一条 SQL,代码会非常混乱。

这时候就可以使用 MyBatis 动态 SQL。

一、为什么需要动态 SQL?

普通 SQL 是固定的:

sql 复制代码
select * from emp where name like '%张三%' and gender = 1;

但是实际查询时,namegender 可能都不是必传参数。

所以我们希望 SQL 可以根据参数自动变化:

text 复制代码
传 name:按姓名查
传 gender:按性别查
都传:两个条件一起查
都不传:查询全部

这就是动态 SQL 的作用。

二、if 标签的使用

<if> 用来判断某个条件是否成立。

xml 复制代码
<select id="list" resultType="com.example.pojo.Emp">
    select *
    from emp
    where
        <if test="name != null and name != ''">
            name like concat('%', #{name}, '%')
        </if>
</select>

这里的意思是:如果 name 不为空,就拼接姓名查询条件。

但是这样写有一个问题:如果 name 为空,SQL 会变成:

sql 复制代码
select * from emp where

这条 SQL 是错误的,所以还需要配合 <where> 使用。

三、where 标签的使用

<where> 会自动生成 where 关键字,并且会自动去掉多余的 andor

xml 复制代码
<select id="list" resultType="com.example.pojo.Emp">
    select id, username, name, gender, phone
    from emp
    <where>
        <if test="name != null and name != ''">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
    </where>
    order by update_time desc
</select>

这样无论前端传几个条件,SQL 都能正常拼接。

四、Controller 层实现

java 复制代码
@GetMapping
public Result list(String name, Integer gender) {
    List<Emp> empList = empService.list(name, gender);
    return Result.success(empList);
}

Controller 负责接收前端传来的查询参数,然后调用 Service。

五、Service 层实现

java 复制代码
@Override
public List<Emp> list(String name, Integer gender) {
    return empMapper.list(name, gender);
}

Service 这里没有复杂业务,只是把参数继续传给 Mapper。

六、Mapper 层实现

java 复制代码
List<Emp> list(String name, Integer gender);

对应 XML:

xml 复制代码
<select id="list" resultType="com.example.pojo.Emp">
    select id, username, name, gender, phone
    from emp
    <where>
        <if test="name != null and name != ''">
            name like concat('%', #{name}, '%')
        </if>
        <if test="gender != null">
            and gender = #{gender}
        </if>
    </where>
</select>

这就是最常见的条件查询动态 SQL。

七、foreach 标签的使用

<foreach> 常用于批量删除。

比如前端传来多个 id:

text 复制代码
ids=1,2,3

Mapper XML 可以这样写:

xml 复制代码
<delete id="deleteByIds">
    delete from emp
    where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

最终 SQL 类似:

sql 复制代码
delete from emp where id in (1,2,3);

八、总结

动态 SQL 是 MyBatis 中非常重要的知识点,尤其是在条件查询和批量操作中经常使用。

<if> 用来判断条件是否拼接,<where> 用来自动处理 where 和多余的 and<foreach> 常用于遍历集合,完成批量删除、批量新增等操作。

相关推荐
記億揺晃着的那天1 小时前
Windows 通过 Java 获取可用端口的一个坑:Hyper-V 保留端口导致 UDP 绑定失败
java·windows·udp
组合缺一1 小时前
SolonCode(编码智能体)支持鸿蒙 PC
java·华为·ai·ai编程·harmonyos·solon·soloncode
小bo波1 小时前
用匿名内部类优雅地计算方法执行时间
java·设计模式·性能测试·模板方法模式·lambda·代码优化·匿名内部类
拾光师1 小时前
Java AIO 详解:异步非阻塞 IO 的实现与实践
后端
折哥的程序人生 · 物流技术专研1 小时前
Tomcat 严重警告:JDBC 驱动未注销 + 工作线程泄漏 —— 原因、影响与彻底修复(生产级终极指南)
java·运维·数据库·mysql·oracle·tomcat
一个儒雅随和的男子1 小时前
sentinel底层原理剖析以及实战优化
java·网络·sentinel
伊灵eLing1 小时前
GoLang 语言基础
开发语言·后端·golang
两年半的个人练习生^_^1 小时前
JMM 进阶:彻底理解 synchronized 实现原理
java·开发语言
techdashen2 小时前
What is maintenance, anyway?
开发语言·后端·rust