在 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()
。
二、避免空指针的最佳实践
- 使用
<if test="xxx != null">
安全判断 null<if test="name != null"> AND name = #{name} </if>
- 尽量避免对参数直接做方法调用
<!-- 不要这样写 --> <if test="name.length() > 0"> ... </if> <!-- 可以这样写 --> <if test="name != null and name != ''"> ... </if>
- 使用 Map 传参,可以更灵活地控制参数存在与否
Map<String, Object> params = new HashMap<>(); params.put("name", null);
- 开启日志,观察最终生成的 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 | 不报错,但结果需小心 |