779 字
约 2 分钟
5
S08-B03 · 动态 SQL:`<if>` / `<where>` / `<foreach>`

适用读者:用 StringBuilder 拼过 SQL 的人。
前置:S08-B02。
覆盖旧文:900(MyBatis 支持动态 SQL 吗,100 点)。
上一篇:S08-B02 · 参数与结果映射:#{} vs ${}
下一篇:S08-B04 · MyBatis-Plus 基础。


1. 一句话结论

动态 SQL 的本质是"用标签生成 SQL 片段",解决手拼 SQL 的三个问题:多余的 and、多余的 where、以及逗号处理。

手拼 SQL 的问题 标签解法
where and name=? <where> 自动去掉开头的 and/or
集合遍历的逗号 <foreach> 的 separator
分支判断 <if test="...">

2. 五个核心标签

标签 作用
<if test="cond"> 条件拼接
<choose>/<when>/<otherwise> 多选一(类似 switch)
<where> 自动加 where 并去掉多余 and
<set> 更新语句自动去掉尾部逗号
<foreach> 集合遍历(in 查询、批量插入)

3. 标准写法

<select id="search" resultType="User">
  select * from sys_user
  <where>
    <if test="name != null and name != ''">and user_name = #{name}</if>
    <if test="minAge != null">and age &gt;= #{minAge}</if>
  </where>
  order by id
</select>
<update id="updateSelective">
  update sys_user
  <set>
    <if test="userName != null">user_name = #{userName},</if>
    <if test="age != null">age = #{age},</if>
  </set>
  where id = #{id}
</update>
<select id="byIds" resultType="User">
  select * from sys_user where id in
  <foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</select>

4. 三个容易踩的点

点 说明
test 里的 != '' 空串判断要写(null 与 '' 是两种情况)
<foreach> 的 collection 名 单参数 List 默认 list;@Param 后用参数名
<where> 不解决"没有条件" 所有 <if> 都不成立时会变成 select * from t(全表)——要加兜底条件

最后一条最危险:动态条件全为空 → 全表扫描。


5. 与 MP 的 Wrapper 怎么选

场景 选
固定 SQL + 少量条件 XML 动态 SQL(可读)
条件由代码动态组合(多分支) Wrapper(B05)
复杂联表/子查询 XML(Wrapper 表达力有限)

判据:"这个 SQL 会被 3 个以上场景复用吗?" 会 → XML;不会且条件多 → Wrapper。


6. 五个误区

误区 真相
"<where> 保证不会全表" 条件全空时就是全表
"<if test=\"name != null\"> 足够" 空串仍会拼进去
"<foreach> 的 collection 随便写" 名字不对会报错
"动态 SQL 只有 <if>" 还有 choose/where/set/foreach/trim
"XML 一定比注解好" 简单 SQL 用注解更直观

7. 自检

  1. <where> 解决了什么问题?不解决什么问题?
  2. <foreach> 的 collection 什么时候是 list、什么时候是参数名?
  3. 为什么 test 里要判空串?
  4. XML 与 Wrapper 怎么选?
  5. 动态条件全为空会生成什么 SQL?

8. 下一篇

S08-B04 · MyBatis-Plus 基础:CRUD、注解、逻辑删除

动态 SQL 讲完,下一篇讲"少写 SQL"的路线:MP 的 CRUD、逻辑删除与乐观锁。


本篇属于系列《S08 · MyBatis 持久层》。旧文来源:A-900。

S08-B03 · 动态 SQL:`<if>` / `<where>` / `<foreach>`
https://www.clxhxhhr.top/posts/5284/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。