在 MyBatis 中处理空参数(null)时,如果使用不当,确实可能会出现 NullPointerException,但只要掌握正确的方法,一般是可以避免的。下面详细说明:

一、MyBatis 中参数为 null 时的常见行为

1. 直接传入 null 会怎样?

  • 如果你直接将 null 作为参数传入 Mapper 方法,比如: mapper.selectByName(null); 而你的 SQL 是这样写的: SELECT * FROM user WHERE name = #{name} MyBatis 会正常执行 SQL,只是将 name = null 带入。但 SQL 中 name = null 是无效的(因为应该是 IS NULL 才对),所以不会报错,但不会返回任何结果

2. 如果在 <if> 标签中判断 null,但没写好,会报错吗?

<if test="name != null">
  AND name = #{name}
</if>
  • 这写法是对的。如果 name 是 null,这段 SQL 就不会被拼接。
  • 如果写错,比如: <if test="name.length() > 0"> 这时候如果 name 是 null,就会在运行时抛出 NullPointerException,因为调用了 null 的 .length()

二、避免空指针的最佳实践

  1. 使用 <if test="xxx != null"> 安全判断 null <if test="name != null"> AND name = #{name} </if>
  2. 尽量避免对参数直接做方法调用 <!-- 不要这样写 --> <if test="name.length() > 0"> ... </if> <!-- 可以这样写 --> <if test="name != null and name != ''"> ... </if>
  3. 使用 Map 传参,可以更灵活地控制参数存在与否 Map<String, Object> params = new HashMap<>(); params.put("name", null);
  4. 开启日志,观察最终生成的 SQL,有助于调试 null 参数行为

三、Mapper 接口调用时传 null 有哪些影响?

单个参数为 null:

User user = mapper.getById(null);
  • SQL 中用 #{id} 替换,会出现 id = null,逻辑上不成立,但不会报空指针

多个参数,某一个为 null:

@Select("SELECT * FROM user WHERE id = #{id} AND name = #{name}")
User get(@Param("id") Integer id, @Param("name") String name);
  • 如果 name 为 null,而你没做判断,会变成 name = null,不符合 SQL 语义。

四、小结

情况是否抛出 NullPointerException
直接传 null 到 #{param}不会,但 SQL 结果可能为 0
<if test="param != null">安全
<if test="param.length() > 0"> 且 param 为 null会抛出 NPE
多个参数用 @Param 时某个为 null不报错,但结果需小心