注意了!mybatis中<if>条件判断,遇到带数字单字符有坑!

mybatis判断条件<if>与单字符数字比较,会判断错误。大家是否踩过这个坑?

1.代码复现

先看这个例子:

//UserInfoTab 对象
@Data
public class UserInfoTab {
    private Integer id;

    private String userName;

    private String userId;
    ...
}

mybatis 查询

 <select id="selectByUserInfo" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from user_info_tab a
    <where>
      <if test="userId == '1' ">
        and a.user_name = 'tianluoboy'
      </if>
      <if test="userId != '1' ">
        and a.user_name != 'tianluoboy'
      </if>
    </where>
  </select>

目前用户表的数据:

图片

现在我的单元测试查询是这样的:

    @Test
    void testQueryUserInfo(){
        List<UserInfoTab> userInfoTabList = userInfoTabDao.selectByUserInfo("1");
        if (CollectionUtils.isEmpty(userInfoTabList)) {
            userInfoTabList.forEach(System.out::println);
        }
    }

如果这个条件生效:

<if test="userId == '1' ">
        and a.user_name = 'tianluoboy'
</if>

我应该查到tianluoboy这条记录,但是事实查到的结果,却是:

图片

也就是说<if test="userId == '1' ">这个条件不生效。

2. 正确的使用方法

如果改成用双引号包着"1",或者用toString()转换一下,则是可以正确查出来的:

 <if test='userId == "1"'>
        and a.user_name = 'tianluoboy'
</if>

<if test="userId == '1'.toString()">
   and a.user_name = 'tianluoboy'
</if>

3. 原因解析

Mybatis 是使用OGNL表达式来解析的,'1'会解析为字符Character,一个字符Character和一个String 当然不相等,这就是为什么<if test="userId == '1' ">不生效。

图片

大家有兴趣可以去debug看看源码哈,这个类:

org.apache.ibatis.ognl.OgnlOps

关键方法是这个:

public static int compareWithConversion(Object v1, Object v2) {
        label75: {
            int result;
            if (v1 == v2) {
                result = 0;
            } else {
                int t1 = getNumericType(v1);
                int t2 = getNumericType(v2);
                int type = getNumericType(t1, t2, true);
                switch (type) {
                    case 6:
                        result = bigIntValue(v1).compareTo(bigIntValue(v2));
                        break;
                    case 7:
                    case 8:
                        break label75;
                    case 9:
                        result = bigDecValue(v1).compareTo(bigDecValue(v2));
                        break;
                    case 10:
                        if (t1 != 10 || t2 != 10) {
                            break label75;
                        }

                        if (v1 instanceof Comparable && v1.getClass().isAssignableFrom(v2.getClass())) {
                            result = ((Comparable)v1).compareTo(v2);
                            break;
                        }

                        if (!(v1 instanceof Enum) || !(v2 instanceof Enum) || v1.getClass() != v2.getClass() && ((Enum)v1).getDeclaringClass() != ((Enum)v2).getDeclaringClass()) {
                            throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());
                        }

                        result = ((Enum)v1).compareTo(v2);
                        break;
                    default:
                        long lv1 = longValue(v1);
                        long lv2 = longValue(v2);
                        return lv1 == lv2 ? 0 : (lv1 < lv2 ? -1 : 1);
                }
            }

            return result;
        }

        double dv1 = doubleValue(v1);
        double dv2 = doubleValue(v2);
        return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值