mybatis 标签不生效主因是空字符串、"0"、数字0被视作非空,仅null和不存在属性被跳过;需用status != null and status != ''判空,避免调用java方法,多须配防语法错误。

MyBatis <if></if> 标签为什么有时不生效?
常见现象是条件写了但 SQL 没变,比如 status 为 null 时仍拼进了 AND status = #{status}。根本原因是 MyBatis 对空字符串、"0"、数字 0 都视为“非空”,只对 null 和不存在的属性做跳过。
-
<if test="status != null and status != ''"></if>才能过滤空字符串 - 数字字段别用
!= '',改用!= null或具体值判断(如id > 0) - 避免在
test表达式里调用方法(如list.size() > 0),MyBatis 不支持任意 Java 方法调用,只支持 OGNL 基础语法 - 多个
<if></if>并列时,注意 SQL 结构合法性——比如开头或结尾多出AND,得靠<where></where>或手写WHERE 1=1
用 <choose></choose> 替代一堆 <if></if> 的实际场景
当需要“if-else if-else”逻辑(比如按不同字段查,但只走一个分支),<choose></choose> 更安全。它天然保证最多一个分支执行,不会因条件重叠导致 SQL 错误。
-
<when test="id != null"></when>和<when test="name != null"></when>不会同时触发 - 必须配
<otherwise></otherwise>吗?不是,但漏写容易导致无匹配时 SQL 缺少关键 WHERE 条件 - 注意
<choose></choose>本身不处理 SQL 拼接细节,AND还得自己写,建议配合<where></where>使用 - 别把
<choose></choose>当 switch 用在循环里——它不支持动态 case 名称,只能硬编码 test 表达式
<foreach></foreach> 遍历 List/Array 时最容易错的三件事
报错 BindingException: Parameter 'xxx' not found 或生成 SQL 多了逗号、少了括号,基本都卡在这几个点上。
- 传参必须是
List、Array或带@Param注解的参数名,不能直接传int[]还不标@Param("ids") -
collection属性名要和实际一致:collection="list"(默认)、collection="array"(数组)、collection="ids"(@Param("ids")时) -
open/close/separator是纯字符串包装,separator=","会在每个元素后加逗号,包括最后一个——除非用<foreach></foreach>内置的智能分隔(它其实不会多加),但手动写IN (#{item})时务必包在open="IN (" close=")"里
XML 动态 SQL 和注解方式的兼容性陷阱
很多人想混用 XML 和 @Select 注解,结果 <if></if> 在注解里直接报错——因为注解不解析 XML 标签,只认字符串拼接。
- XML 中的
<if></if>、<foreach></foreach>只在<select></select>/<update></update>等标签内有效,写在<sql></sql>片段里也 OK,但不能出现在 Java 注解里 - 想用动态逻辑又不想写 XML?只能用
ScriptProvider或第三方扩展,原生 MyBatis 注解不支持 OGNL 表达式 - 同一个 Mapper 接口里,XML 和注解方法不能同名,否则启动报
MapperParsingException——MyBatis 会尝试加载两个定义
<foreach></foreach> 里再套 <if></if>,这时候 test 表达式作用域、collection 名称、参数绑定层级很容易串,调试得靠日志开到 DEBUG 看最终生成的 SQL。










