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

相关推荐
一 乐6 分钟前
自习室座位预约管理系统|基于springboot + vue自习室座位预约管理系统(源码+数据库+文档)
java·vue.js·spring boot
行百里er8 分钟前
轻量级 Spring 监测工具——Spring Insight 发布了
spring boot·后端·监控
此时不提桶,更待何时25 分钟前
02-02-B-AQS与JUC锁面试与生产事故实战
java
音符犹如代码28 分钟前
Kafka 接入 AI 的三条路线:MCP 提案、会话记忆与实时上下文
java·大数据·ai·kafka
vx_BS8133032 分钟前
【项目编号:project51629】Spring Boot 乡村自来水缴费系统:把抄表、水费生成与在线缴费做成一条数字化闭环
java·spring boot·eclipse·tomcat·maven
程序员阿黄36 分钟前
基于 Django 与 Vue 3 的智能实验室预约系统设计与实现
后端·python·mysql·django·vue·毕设
qq_2695067541 分钟前
第29课-Servlet基础
java
光影少年43 分钟前
Koa 为什么使用洋葱模型
后端·node.js·koa
用户298698530141 小时前
Python 如何实现 Word 与 RTF 文档互转
后端·python·api
打工仔折腾 AI1 小时前
用 Shell 脚本自动部署 mysqld_exporter 并接入 Prometheus 远程抓取
人工智能·后端·python·性能优化·ai agent 实战