id的条件语句中包含 id != “”,传参数的时候id设置的值为0
有可能是因为Integer类型在和 “” 比较的时候,“” 会被默认转换成Integer类型去做比较,从而变成 id != 0,导致等式不成立
我们直接从获取绑定sql中开始分析
org.apache.ibatis.mapping.MappedStatement#getBoundSql
public BoundSql getBoundSql(Object parameterObject) {
//从这个方法我们就可以找到sql是如何被拼接的
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
......
return boundSql;
}
看你写的是动态sql还是静态sql,我这边写的是动态sql
org.apache.ibatis.scripting.xmltags.DynamicSqlSource#getBoundSql
获取到 语句内的内容
public BoundSql getBoundSql(Object parameterObject) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
//将 语句内的内容划分为三部分:statisTextSqlNode、MixedSqlNode、TextSqlNode
rootSqlNode.apply(context);
.......
return boundSql;
}
留意解析 WhereSqlNode 节点的信息
org.apache.ibatis.scripting.xmltags.MixedSqlNode#apply
org.apache.ibatis.scripting.xmltags.TrimSqlNode#apply
为什么会跳到TrimSqlNode节点?因为WhereSqlNode节点继承了,TrimSqlNode节点但是没有重写apply方法
public boolean apply(DynamicContext context) {
FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
//获取当前节点的内容,然后继续调用父类的apply方法继续迭代解析
boolean result = contents.apply(filteredDynamicContext);
filteredDynamicContext.applyAll();
return result;
}
解析到if条件时会跳转到之类实现
org.apache.ibatis.scripting.xmltags.IfSqlNode#apply
public boolean apply(DynamicContext context) {
//test: id != null and id != ''
//context.getBindings() 包含全部入参
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
org.apache.ibatis.scripting.xmltags.ExpressionEvaluator
public boolean evaluateBoolean(String expression, Object parameterObject) {
//通过Ognl去进行 表达式计算并缓存当前表达式
Object value = OgnlCache.getValue(expression, parameterObject);
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
}
return value != null;
}
public static Object getValue(String expression, Object root) {
try {
Map context = Ognl.createDefaultContext(root, MEMBER_ACCESS, CLASS_RESOLVER, null);
// 解析成Ognl指定的表达式
//使用Ognl去 计算表达式
return Ognl.getValue(parseExpression(expression), context, root);
} catch (OgnlException e) {
......
}
}
org.apache.ibatis.ognl.SimpleNode#getValue
org.apache.ibatis.ognl.SimpleNode#evaluateGetValueBody
//比如: 表达式 :id != ''、入参: id=0
//常量值为:0(入参值)、''
protected Object evaluateGetValueBody(OgnlContext context, Object source) throws OgnlException {
context.setCurrentObject(source);
context.setCurrentNode(this);
if (!this._constantValueCalculated) {
this._constantValueCalculated = true;
boolean constant = this.isConstant(context);
if (constant) {
this._constantValue = this.getValueBody(context, source);
}
this._hasConstantValue = constant;
}
//根据条件提供的表达式,在getValueBody(); 时会跳转 ASTEq#getValueBody
return this._hasConstantValue ? this._constantValue : this.getValueBody(context, source);
}
org.apache.ibatis.ognl.ASTEq#getValueBody
//表达式为:id != ''
protected Object getValueBody(OgnlContext context, Object source) throws OgnlException {
//v1 = 0
Object v1 = this._children[0].getValue(context, source);
//v2 = ''
Object v2 = this._children[1].getValue(context, source);
//在OgnlOps的底层中比较的时候,会将 0、'' 转换成double进行比较
//注意当前equals,返回的结果集是相反的,对应xml中的表达式应该为:!OgnlOps.equal(v1, v2)
return OgnlOps.equal(v1, v2) ? Boolean.TRUE : Boolean.FALSE;
}
public static boolean equal(Object v1, Object v2) {
if (v1 == null) {
return v2 == null;
//留意当前的 !isEquals
} 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;
}
}
public static boolean isEqual(Object object1, Object object2) {
boolean result = false;
if (object1 == object2) {
result = true;
} else if (object1 != null && object1.getClass().isArray()) {
.........
}else{
//留意 compareWithConversion 方法
result = object1 != null && object2 != null
&& (object1.equals(object2) || compareWithConversion(object1, object2) == 0);
}
return result;
}
public static int compareWithConversion(Object v1, Object v2) {
int result;
if (v1 == v2) {
result = 0;
} else {
// 0 = int, t1 = 4
int t1 = getNumericType(v1);
// '' = String,t2 = 10
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: //留意当前case 没有 break;
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:
// v1 = 0, dv1 = 0.0
double dv1 = doubleValue(v1);
//v2 = '', dv2 = 0.0
double dv2 = doubleValue(v2);
//返回结果集为 true,从而得到
//OgnlOps.equal(0, '') = true
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;
}