【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> 常用于遍历集合,完成批量删除、批量新增等操作。

相关推荐
Csvn1 小时前
📊 SQL 入门 Day 8:集合操作 — 用 SQL 做数学里的"并交差"
后端·sql
腻害兔2 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
碎光拾影2 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Miao121313 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
码事漫谈3 小时前
告别数据孤岛与AI“水土不服”:金仓多模融合时序库如何让数据真正服务于业务
后端
IT_陈寒4 小时前
Redis的持久化配置把我坑惨了:你以为数据安全了?
前端·人工智能·后端
星栈4 小时前
Node 接口该写同步还是异步?
后端·node.js
红烧大青虫4 小时前
HarmonyOS应用开发实战:小事记 - UIAbility 的冷启动/热启动/后台启动三种场景与 launchParam 解析
后端·华为·harmonyos·鸿蒙系统
码事漫谈4 小时前
AI Token 缓存:命中省 10 倍,不命中白扔钱
后端