在 MyBatis 的 <if> 标签中,表达式 isDeduc != null and isDeduc == 0 是基于 OGNL (Object-Graph Navigation Language) 表达式进行解析的。OGNL 在处理不同类型的数据时会进行隐式类型转换,这就可能导致一些看似不合理的判断结果。
true?OGNL 在处理表达式时,如果字段类型不匹配,会尝试进行隐式类型转换。例如:
String),但表达式中使用了 isDeduc == 0,OGNL 会尝试将字符串转换为数字。"") 在转换为数字时,会被解析为 0。假设 isDeduc 的值是空字符串 (""),表达式 isDeduc != null and isDeduc == 0 的执行过程如下:
isDeduc != null:空字符串 ("") 是一个有效的字符串对象,不为 null,所以条件为 true。isDeduc == 0:由于 isDeduc 是字符串类型,OGNL 会尝试将其转换为数字:
"") 被转换为 0。isDeduc == 0 的结果也为 true。最终,整个表达式的结果为 true。
为了避免这种隐式类型转换带来的意外行为,建议在使用 <if> 标签时,明确字段的类型,并在判断条件中加入类型检查。
java.lang.Number 类型如果 isDeduc 是数字类型(如 Integer 或 Double),可以直接使用:
<if test="isDeduc != null and isDeduc == 0">
AND B.deduc_percent = 0
</if>
这样可以避免类型转换问题。
如果 isDeduc 是字符串类型(如 String),需要显式地将其转换为数字类型:
<if test="isDeduc != null and isDeduc.length() > 0 and Integer.parseInt(isDeduc) == 0">
AND B.deduc_percent = 0
</if>
这段代码的逻辑如下:
isDeduc != null:确保 isDeduc 不为 null。isDeduc.length() > 0:确保 isDeduc 不是空字符串。Integer.parseInt(isDeduc) == 0:将字符串显式转换为整数,并与 0 进行比较。如果字段类型是字符串,但在业务逻辑中需要与数字比较,建议在 Java 代码中进行类型转换,而不是在 XML 文件中直接比较。这样可以避免 OGNL 的隐式类型转换行为。
"") 被转换为 0。Integer.parseInt() 或类似的显式转换方法。通过这些改进,可以确保 <if> 标签的判断条件更加准确和可靠。