MyBatis中Integer值为0时,无法作为判断条件
1.导语
最近在工作中使用SpringBoot+MyBatis时,遇见一个小问题,代码如下:
<if test="status != null and status != ''">
Status,
</if>
status是一个Integer类型的参数,当我传递值为0的时候,MyBatis不会把这个条件添加到SQL中。
2.源码分析
为什么会出现上诉的问题呢,我也很困扰,经过排查,发现并不是传参出现问题,参数能顺利的传递到mapper层,那么我们可以推断,问题是出现在Mybatis源码中。
根据ITEYE的一位博主的博客,并且通过这位博主的方法,我们追踪Mybatis的源码,一直到ExpressionEvaluator这个类,发现在这个类中有如下的方法
public class ExpressionEvaluator {
public boolean evaluateBoolean(String expression, Object parameterObject) {
Object value = OgnlCache.getValue(expression, parameterObject);
if (value instanceof Boolean) return (Boolean) value;
if (value instanceof Number) return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);
return value != null;
}
在这段代码里面,你是不是看到了evaluateBoolean方法的第一行使用了Ognl表达式,通过Ognl表达式,我们可以知道在它的语法中 0 == ’ ’ == false,因此我们写的是不成立的。由此,我们也得出一个提示,在MyBatis的if判断中,除了String类型可以和 ’ ’ 进行比较之外,其余的类型最好都不要与 ’ ’ 作比较,这是一种不规范的写法。
3.解决方式
3.1
把上面的status != ’ ‘去掉即可
3.2
或者在 status != ’ ‘后面继续添加 or status == 0
4.总结
针对上述问题,我们最好的方式是采用3.1的处理方法,除了String类型的参数之外,其余类型不要和 ’ ’ 进行比较。另外,由于Ognl表达式对char类型也有处理,因此我们在做的时候也需要注意:如果你的判断是 XXX == ‘A’的方式,会出问题,因为OGNL会把A作为char类型处理;因此需要改成 XXX == “A”,用双引号括起来。