MyBatis 动态 SQL 使用详解

一、什么是动态 SQL?

动态 SQL 是指根据传入参数,动态拼接生成 SQL 语句,不需要写多个 SQL 方法。MyBatis 提供了 等标签来实现这类操作


✅ 二、动态 SQL 的优点

优点 说明
✔️ 灵活 同一个 SQL 根据不同参数拼接不同条件(if / where),非常适合查询页面
✔️ 减少代码重复 比如模糊搜索功能,不再需要写多个 SQL 接口方法
✔️ 可读性强(配合 XML) 结构清晰,尤其用 / /
✔️ SQL 控制权在开发者手中 和 Hibernate/JPA 相比,MyBatis 更易于优化复杂 SQL
✔️ 易于维护多条件组合查询 如管理后台的搜索表单、动态筛选等功能

❌ 三、动态 SQL 的缺点

缺点 说明
❌ 编写略繁琐 XML 写法需要嵌套多个标签,容易出错,特别是嵌套复杂条件时
❌ 可读性下降(过度嵌套) 动态 SQL 太复杂时,XML 显得臃肿不易读
❌ 不利于 IDE 自动提示 逻辑写在 XML 中,IDE 很难做类型检查和智能提示
❌ SQL 拼接错误不易发现 某些条件组合可能拼错 SQL,运行期才报错
❌ 与注解风格冲突 注解方式不支持复杂的动态 SQL,只能用 XML 实现动态拼接

️ 四、动态 SQL 适用场景

✅ 最适合的场景:

场景 举例
条件查询页面 多条件组合搜索,如:用户列表查询、订单筛选、日志检索
后台管理系统 如 admin 页面支持 name、status、时间区间等动态条件
报表查询系统 查询维度、范围、排序条件全是动态的
批量操作 IN 查询、批量更新、删除(用
多字段更新 UPDATE 语句中字段非空才更新(用 标签)

❌ 不推荐使用的场景:

场景 原因
常规增删改查 逻辑简单,不需要动态拼接
SQL 条件固定 写死 SQL 语句更清晰、维护方便
条件复杂但变化不大 建议写多个 SQL 方法,避免 XML 太臃肿

五、小结一张表

点评维度 动态 SQL 表现
灵活性 ⭐⭐⭐⭐⭐ 超高
编写复杂度 ⭐⭐⭐❌ 中等偏高
可维护性 ⭐⭐⭐ 中等
性能控制 ⭐⭐⭐⭐⭐ 好
推荐场景 多条件查询、批量操作

✨ 示例对比

✅ 使用动态 SQL:


❌ 不使用动态 SQL(需要写多个方法):





MyBatis 动态 SQL 标签速查表

标签 作用 示例 注意事项
条件判断 AND name = #{name} test 支持 OGNL 表达式,如 != null && name != ''
分支选择(类似 switch-case) 见下方示例 只能命中一个 ,类似 if…else
自定义前缀、后缀、去掉多余的分隔符 ` … `
自动加 WHERE 并去掉首个 AND/OR AND ... 自动处理空条件时避免语法错误
自动加 SET 并去掉多余逗号(用于 UPDATE) name=#{name}, 适用于动态更新字段
遍历集合,构造 IN 语句、批量插入等 见下方示例 支持 list、array、Map,常用于 IN (...)
创建一个变量,可用于字符串拼接等 常配合模糊查询使用

示例合集

1️⃣ 使用示例

<select id="selectUser" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        if>
        <if test="age != null">
            AND age = #{age}
        if>
    where>
select>

2️⃣ / / 示例

<select id="selectUser" resultType="User">
    SELECT * FROM user
    <where>
        <choose>
            <when test="name != null">
                AND name = #{name}
            when>
            <when test="age != null">
                AND age = #{age}
            when>
            <otherwise>
                AND status = 'active'
            otherwise>
        choose>
    where>
select>

3️⃣ 示例(手动 WHERE 拼接)

<select id="selectUser" resultType="User">
    SELECT * FROM user
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        <if test="name != null">AND name = #{name}if>
        <if test="age != null">AND age = #{age}if>
    trim>
select>

4️⃣ 示例(动态更新)

<update id="updateUser">
    UPDATE user
    <set>
        <if test="name != null">name = #{name},if>
        <if test="age != null">age = #{age},if>
    set>
    WHERE id = #{id}
update>

5️⃣ 示例(IN 查询)

<select id="selectByIds" resultType="User">
    SELECT * FROM user WHERE id IN
    <foreach collection="idList" item="id" open="(" separator="," close=")">
        #{id}
    foreach>
select>
语法片段 含义
id="selectByIds" 这是 Mapper 接口中方法对应的 SQL ID
resultType="User" 查询结果会映射成 User
collection="idList" 传入的是一个集合参数名,比如一个 List 类型的参数
item="id" 遍历集合中的每个元素,当前元素命名为 id
open="(" 拼接 SQL 时,开头加一个左括号 (
separator="," 每个参数之间用逗号隔开
close=")" 最后一个参数后加上右括号 )
#{id} 当前遍历元素的值,作为 SQL 参数传入(防 SQL 注入)

6️⃣ 示例(模糊搜索)

<select id="searchByName" resultType="User">
    <bind name="pattern" value="'%' + name + '%'" />
    SELECT * FROM user WHERE name LIKE #{pattern}
select>
部分 解释
定义一个 SQL 查询方法,ID 是 searchByName
resultType="User" 查询结果会封装成 User 对象
MyBatis 提供的 标签: 动态创建一个变量 pattern,它的值是 '%xxx%' 这样的字符串,供后面 SQL 使用
value="'%' + name + '%'" 拼接模糊匹配字符串(注意这里的 '%' 是字符串,需要加单引号
#{pattern} MyBatis 会将 pattern 的值安全地替换进 SQL,防止 SQL 注入

小技巧总结

目标 建议用法
多条件查询 配合
动态更新字段 配合
IN 查询
模糊搜索
模拟 if…else

你可能感兴趣的:(后端,mybatis,sql,数据库)