前言
在使用Mybatis的时候,曾遇到过一个奇怪的问题,当使用<if test="status != null and status != ''">
判空操作时,如果status为0的时候,该判断条件的值为false,也就是说Mybatis此时把0作为null来进行判断的。
遇到这个问题的时候,翻看Mybatis的源码,发现其在ExpressionEvaluator.java
类的evaluateBoolean
方法处返回了false。
场景分析
数据库字段
1 | `pay_status` int(11) NOT NULL DEFAULT '0' COMMENT '支付状态 0-未支付 1-已支付', |
按照一般的逻辑来看,查询语句需要写成这样的形式:
1 | select * from order_pay pay WHERE pay.deal_id = 1 |
当查询参数不传递未支付或者已支付条件时,就需要查询payStatus为0和1的全部结果,也就是说没有条件and pay.pay_status = #{payStatus}
,但事实就纠结了,当payStatus传递的参数为1时,if条件的结果为true,也就是说sql语句变成了select * from order_pay pay WHERE pay.deal_id = 1 and pay.pay_status=1
,查询结果正常,但如果payStatus为0此时,sql语句变成了select * from order_pay pay WHERE pay.deal_id = 1
,与预期结果select * from order_pay pay WHERE pay.deal_id = 1 and pay.pay_status=0
显然是不符的!
Mybatis自作主张的把payStatus为0的条件当做了if的false结果!
解决办法
方法一
payStatus是Integer类型的,把payStatus != ''
去掉就可以了。
那么现在重新来看,先前的做法本来就有问题,integer类型的,干嘛要用payStatus!=''
来进行判断,这显然是不对的,从原则上来讲,<if test="payStatus != null and payStatus != ''">
该判断条件只能来判断payStatus为string类型的,不能用来判断integer类型。
但由此引发一个疑问:
<if test="payStatus != null and payStatus != ''">
判断不是为空,对于Integer类型就是在判断不为0么?
方法二
对传递参数拦截
1 | public static int parseStringToInt(Object parameter, int defualtValue) { |
1 | vo.addParams("status", StrUtil.parseStringToInt(vo.getParams("status"), -1)); |
也就是说在查询所有支付状态的订单时,把payStatus的值转换为-1。
重构Mybatis的查询语句
1 | select * from order_pay pay WHERE pay.deal_id = 1 |