MyBatis 动态 SQL 详解:灵活构建复杂查询条件

简介: MyBatis提供强大的动态SQL机制,通过`<if>`、`<where>`、`<foreach>`等标签实现条件判断、循环拼接,避免手动字符串处理。支持智能WHERE、SET生成,兼容多数据库模糊查询,提升代码安全性与可维护性,适用于复杂查询、批量操作等场景。

在实际开发中,SQL 语句往往不是固定的,而是需要根据传入参数动态拼接。例如:用户可能只填写部分搜索条件,或管理员需要按不同状态筛选数据。MyBatis 提供了一套强大的 动态 SQL 机制,通过 XML 标签实现条件判断、循环、拼接等逻辑,避免手写繁琐的字符串拼接。

本文将系统介绍 MyBatis 中最常用的动态 SQL 标签及其使用场景。


一、<if>:条件判断

用于根据条件决定是否包含某段 SQL。

<select id="findUsers" resultType="User">
  SELECT * FROM user WHERE 1=1
  <if test="username != null and username != ''">
    AND username LIKE CONCAT('%', #{username}, '%')
  </if>
  <if test="status != null">
    AND status = #{status}
  </if>
</select>

技巧

使用 WHERE 1=1 可避免因第一个条件不满足导致 WHERE 后无内容的语法错误。但更推荐使用 <where> 标签(见下文)。


二、<where>:智能处理 WHERE 子句

自动处理 AND/OR 的前缀问题,并在无条件时省略整个 WHERE 子句

<select id="findUsers" resultType="User">
  SELECT * FROM user
  <where>
    <if test="username != null">
      username LIKE CONCAT('%', #{username}, '%')
    </if>
    <if test="status != null">
      AND status = #{status}
    </if>
  </where>
</select>

优势

  • 自动去除开头多余的 ANDOR
  • 若所有 <if> 都不满足,则不生成 WHERE,SQL 仍合法。

三、<choose><when><otherwise>:多条件分支

类似 Java 中的 switch...case,只执行第一个满足条件的分支。

<select id="findUserByCondition" resultType="User">
  SELECT * FROM user
  <where>
    <choose>
      <when test="id != null">
        id = #{id}
      </when>
      <when test="username != null">
        username = #{username}
      </when>
      <otherwise>
        status = 'ACTIVE'
      </otherwise>
    </choose>
  </where>
</select>

📌 适用场景:互斥条件,如“按 ID 查”或“按用户名查”,优先级明确。


四、<foreach>:循环遍历集合

常用于 IN 查询、批量插入等场景。

1. IN 查询
<select id="selectByIds" resultType="User">
  SELECT * FROM user
  WHERE id IN
  <foreach collection="ids" item="id" open="(" separator="," close=")">
    #{id}
  </foreach>
</select>
  • collection:传入的集合(List、Array 或 Map 中的 key);
  • item:当前元素变量名;
  • open / close:包裹整个集合的符号;
  • separator:元素之间的分隔符。
2. 批量插入
<insert id="batchInsert">
  INSERT INTO user (username, email) VALUES
  <foreach collection="users" item="user" separator=",">
    (#{user.username}, #{user.email})
  </foreach>
</insert>

⚠️ 注意

若传入的是 List,collection="list";若为数组,collection="array";若为自定义参数(如 @Param("users")),则用对应名称。


五、<set>:智能更新字段

用于 UPDATE 语句,自动处理逗号分隔,并忽略未设置的字段。

<update id="updateUser">
  UPDATE user
  <set>
    <if test="username != null">username = #{username},</if>
    <if test="email != null">email = #{email},</if>
    <if test="status != null">status = #{status}</if>
  </set>
  WHERE id = #{id}
</update>

效果

若只传了 usernamestatus,生成的 SQL 为:

UPDATE user SET username = ?, status = ? WHERE id = ?

自动去除末尾逗号,避免语法错误。


六、<trim>:通用前缀/后缀处理

<where><set> 实际上是 <trim> 的特例。你也可以自定义。

<!-- 等效于 <where> -->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>
<!-- 等效于 <set> -->
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>
  • prefix:添加前缀;
  • prefixOverrides:去除开头指定字符串;
  • suffix / suffixOverrides:同理处理结尾。

七、<bind>:创建变量

可用于模糊查询中预处理参数,避免数据库方言差异。

<select id="findUserByName" resultType="User">
  <bind name="pattern" value="'%' + username + '%'" />
  SELECT * FROM user WHERE username LIKE #{pattern}
</select>

优势:兼容 MySQL、Oracle、PostgreSQL 等不同数据库的 LIKE 语法。


总结:动态 SQL 标签速查表

标签 用途 典型场景
<if> 条件包含 可选查询条件
<where> 智能 WHERE 多条件组合查询
<choose> 多选一分支 互斥条件
<foreach> 循环 IN 查询、批量操作
<set> 智能 SET 动态更新字段
<trim> 自定义修剪 高级控制
<bind> 创建变量 模糊查询、表达式复用

掌握这些动态 SQL 标签,你就能轻松应对各种复杂查询和更新场景,写出既安全又高效的 MyBatis 映射代码。


相关文章
|
Java API Spring
【Springboot】springboot 多线程@EnableAsync和@Async
【Springboot】springboot 多线程@EnableAsync和@Async
683 0
|
SQL XML Java
mybatis之动态SQL常见标签的使用
mybatis之动态SQL常见标签的使用
500 0
|
Java API 数据安全/隐私保护
掌握Spring Boot中的@Validated注解
【4月更文挑战第23天】在 Spring Boot 开发中,@Validated 注解是用于开启和利用 Spring 的验证框架的一种方式,特别是在处理控制层的输入验证时。本篇技术博客将详细介绍 @Validated 注解的概念和使用方法,并通过实际的应用示例来展示如何在项目中实现有效的数据验证
1086 3
|
SQL XML Java
【mybatis】第二篇:@Select注解中加入字段判断
【mybatis】第二篇:@Select注解中加入字段判断
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1640 0
|
SQL XML Java
Mybatis中foreach的使用
【11月更文挑战第12天】MyBatis 的 `foreach` 标签用于在 SQL 语句中遍历集合或数组,支持批量插入、更新及多条件查询等操作。通过设置 `collection`、`item` 等属性,可动态生成 SQL 片段,实现高效的数据处理。示例包括批量插入用户信息、根据 ID 列表查询用户数据以及遍历 Map 查询分类下的产品。
1361 0
|
安全 开发工具 git
图解Git——分支管理《Pro Git》
分支管理是 Git 中的重要机制,支持并行开发和清晰的工作流。常用命令包括:`git branch` 列出所有分支,`git branch -v` 查看最后一次提交,`git branch --merged` 和 `git branch --no-merged` 分别查看已合并和未合并的分支。创建新分支用 `git branch &lt;branch-name&gt;`,删除分支用 `git branch -d`(已合并)或 `-D`(强制删除)。建议定期清理已完成任务的分支,保持代码库整洁,并使用有意义的分支命名规范。注意强制删除未合并分支时可能丢失数据。
409 5
|
Java 数据库连接 mybatis
mybatis注解@Select中添加判断条件<script>
mybatis注解@Select中添加判断条件<script>
1409 0
|
存储 Java 数据处理
Java的Base64加密解密详解
Java的Base64加密解密详解
1021 2
|
设计模式 前端开发 Java