MyBatis动态SQL标签(如<if>、<where>、<set>)用于运行时智能组装SQL片段,避免字符串拼接导致的语法错误、SQL注入和空值问题;<if>通过OGNL表达式控制条件分支,<where>自动处理WHERE关键字及多余AND/OR,<set>安全生成UPDATE语句并去除末尾逗号。

MyBatis 的动态 SQL 标签(如 <if>、<where>、<set>)不是用来“拼接字符串”生成 SQL,而是让 MyBatis 在运行时根据参数条件智能组装 SQL 片段,避免手写字符串拼接带来的语法错误、SQL 注入和空值问题。
用 <if> 控制条件分支
<if> 是最常用的动态标签,通过 test 表达式判断是否包含该 SQL 片段。表达式使用 OGNL 语法,可访问参数对象属性、集合、静态方法等。
例如查询用户,支持按用户名、邮箱、状态任意组合筛选:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
SELECT * FROM user WHERE 1=1
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
<if test="status != null">
AND status = #{status}
</if>
</select>
用 <where> 自动处理 WHERE 和 AND
直接写 WHERE 1=1 虽然可行,但不够优雅。<where> 标签会自动:
- 如果内部有至少一个条件成立,才插入 WHERE 关键字
- 自动去除第一个条件前多余的 AND 或 OR
上面的查询可优化为:
立即学习“Java免费学习笔记(深入)”;
<select id="selectUsers" resultType="User">SELECT * FROM user
<where>
<if test="username != null and username != ''">
username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="email != null and email != ''">
AND email = #{email}
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
</select>
用 <set> 安全生成 UPDATE 语句
更新操作常需动态设置字段,<set> 会:
- 只在有字段需要更新时才添加 SET 关键字
- 自动去掉最后一个逗号(,)
例如只更新非空字段:
<update id="updateUser">UPDATE user
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="email != null and email != ''">
email = #{email},
</if>
<if test="status != null">
status = #{status},
</if>
</set>
WHERE id = #{id}
</update>
其他实用技巧
- 多个条件用
and/or连接,注意括号:用test="(a!=null) and (b!=null)"更清晰 - 判断集合非空:用
test="list != null and list.size() > 0"或更简洁的test="list != null and !list.isEmpty()" - 避免 NPE:对可能为 null 的对象属性,先判空再取属性,如
test="user != null and user.username != null" - 需要复杂逻辑时,可用
<choose><when><otherwise>替代 if-else 链

















