MybatisMapper语句标签test中0与""比较的问题

最近在编写程序在使用mybatis(3.4.6版本) Mapper进行SQL语句映射查询时发现在的test中使用判断语句时,当判断条件为flag!="" 且flag为数字等于0时返回的结果为false

跟踪mybatis的的执行源码时发现。

```java

class ASTNotEq extends ComparisonExpression {

  public ASTNotEq(int id) {

    super(id);

  }

  public ASTNotEq(OgnlParser p, int id) {

    super(p, id);

  }

  protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {

    //获取到用户输入的数据

    Object v1 = this._children[0].getValue(context, source);

    //获取到 flag != "" 中的 ""  也就是写定的后置条件

    Object v2 = this._children[1].getValue(context, source);

    return OgnlOps.equal(v1, v2) ? Boolean.FALSE : Boolean.TRUE;

  }

  public String getExpressionOperator(int index) {

    return "!=";

  }

  public String getComparisonFunction() {

    return "!ognl.OgnlOps.equal";

  }

}

```

跟踪equal得到

```java

public static boolean equal(Object v1, Object v2) {

    if (v1 == null) {

      return v2 == null;

    } else if (v1 != v2 && !isEqual(v1, v2)) {

      if (v1 instanceof Number && v2 instanceof Number) {

        return ((Number)v1).doubleValue() == ((Number)v2).doubleValue();

      } else {

        return false;

      }

    } else {

      return true;

    }

  }

```

可以看到在v1不等于null时,进行isEqual的判断,查看isEqul的代码

```

public static boolean isEqual(Object object1, Object object2) {

    boolean result = false;

    if (object1 == object2) {

      result = true;

    } else if (object1 != null && object1.getClass().isArray()) {

      if (object2 != null && object2.getClass().isArray() && object2.getClass() == object1.getClass()) {

        result = Array.getLength(object1) == Array.getLength(object2);

        if (result) {

          int i = 0;

          for(int icount = Array.getLength(object1); result && i < icount; ++i) {

            result = isEqual(Array.get(object1, i), Array.get(object2, i));

          }

        }

      }

    } else {

      result = object1 != null && object2 != null && (object1.equals(object2) || compareWithConversion(object1, object2) == 0);

    }

    return result;

  }

```

在上述条件中,v1=0且v2=""的情况下,会进行compareWithConversion的判断

```

public static int compareWithConversion(Object v1, Object v2) {

    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 9:

        result = bigDecValue(v1).compareTo(bigDecValue(v2));

        break;

      case 10:

        if (t1 == 10 && t2 == 10) {

          if (v1 instanceof Comparable && v1.getClass().isAssignableFrom(v2.getClass())) {

            result = ((Comparable)v1).compareTo(v2);

            break;

          }

          throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());

        }

      case 7:

      case 8:

        double dv1 = doubleValue(v1);

        double dv2 = doubleValue(v2);

        return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);

      default:

        long lv1 = longValue(v1);

        long lv2 = longValue(v2);

        return lv1 == lv2 ? 0 : (lv1 < lv2 ? -1 : 1);

      }

    }

    return result;

  }

```

继续查看getNumericType方法

```

public static int getNumericType(Object value) {

    if (value != null) {

      Class c = value.getClass();

      if (c == Integer.class) {

        return 4;

      }

      if (c == Double.class) {

        return 8;

      }

      if (c == Boolean.class) {

        return 0;

      }

      if (c == Byte.class) {

        return 1;

      }

      if (c == Character.class) {

        return 2;

      }

      if (c == Short.class) {

        return 3;

      }

      if (c == Long.class) {

        return 5;

      }

      if (c == Float.class) {

        return 7;

      }

      if (c == BigInteger.class) {

        return 6;

      }

      if (c == BigDecimal.class) {

        return 9;

      }

    }

    return 10;

  }

```

可以了解到getNumericType是通过对象的类型,返回其类的指定代码的函数

可以得到 v1为integer类型 返回的结果为4,v2为String类型,返回结果为10

之后进入case判断,通过第二个getNumericType的代码

```

public static int getNumericType(int t1, int t2, boolean canBeNonNumeric) {

    if (t1 == t2) {

      return t1;

    } else if (canBeNonNumeric && (t1 == 10 || t2 == 10 || t1 == 2 || t2 == 2)) {

      return 10;

    } else {

      if (t1 == 10) {

        t1 = 8;

      }

      if (t2 == 10) {

        t2 = 8;

      }

      if (t1 >= 7) {

        if (t2 >= 7) {

          return Math.max(t1, t2);

        } else if (t2 < 4) {

          return t1;

        } else {

          return t2 == 6 ? 9 : Math.max(8, t1);

        }

      } else if (t2 >= 7) {

        if (t1 < 4) {

          return t2;

        } else {

          return t1 == 6 ? 9 : Math.max(8, t2);

        }

      } else {

        return Math.max(t1, t2);

      }

    }

```

最终返回的数值为10,

```java

case 10:

        if (t1 == 10 && t2 == 10) {

          if (v1 instanceof Comparable && v1.getClass().isAssignableFrom(v2.getClass())) {

            result = ((Comparable)v1).compareTo(v2);

            break;

          }

          throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and " + v2.getClass().getName());

        }

      case 7:

      case 8:

        double dv1 = doubleValue(v1);

        double dv2 = doubleValue(v2);

        return dv1 == dv2 ? 0 : (dv1 < dv2 ? -1 : 1);

```

查看case 10:的代码可以得知,只有当两者皆为String类型时,才会进入case 10的条件中进行判断,否则,跳过10 ,进入case 8的语句中 ,也就是默认两者皆为double类型。

查看doubleValue方法

```

public static double doubleValue(Object value) throws NumberFormatException {

    if (value == null) {

      return 0.0D;

    } else {

      Class c = value.getClass();

      if (c.getSuperclass() == Number.class) {

        return ((Number)value).doubleValue();

      } else if (c == Boolean.class) {

        return (Boolean)value ? 1.0D : 0.0D;

      } else if (c == Character.class) {

        return (double)(Character)value;

      } else {

        String s = stringValue(value, true);

        return s.length() == 0 ? 0.0D : Double.parseDouble(s);

      }

    }

  }

```

v1为用户输入值,在此前的场景中为Integer类型的0,可以看到最终结果为

double dv1=0.0

v2为写定的结果,为String类型的"",在判断中通过对String的长度判断进行赋值,而""在判断逻辑中等同于0.0D,结果为double dv2=0.0

最终得出 0==""的结果。

你可能感兴趣的:(MybatisMapper语句标签test中0与""比较的问题)