标签:生效 integer except seq http efault instance tps src
最近遇到的一个关于mybatis的xml条件判断的问题,平时写的都是以判断空属性是否为空,例如:
<if test="type!=null and type !=‘‘">
and status = 1
</if>
所以在这一块并没有足够的重视。
最近刚好要写一个与上边不一样的写法,但是还是以上面的为基础,是对属性的值进行判断:
判断type属性的值
<if test="type!=null and type !=‘‘">
<if test="type==‘6‘">
and status = 61
</if>
<if test="type!=‘6‘">
and status = 2
</if>
</if>
结果就是无论我传什么值,SQL中都是执行的status=2。
在网上也找到了很多解决办法,但是都不是自己想要的结果;
<if test=‘type=="6"‘>
and status = 1
</if>
<if test="type==‘6‘.toString()">
and status = 1
</if>
从参考文章1中可以知道,mybatis使用ognl表达式来进行解析的;下面使用ognl来模拟解析;且不使用上面的两种方法;
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.2.1</version>
</dependency>
// 构建一个OgnlContext对象
OgnlContext context = (OgnlContext) Ognl.createDefaultContext(this,
new DefaultClassResolver(),
new DefaultTypeConverter(),
new DefaultMemberAccess(true));
Map<String,Object> hashMap=new HashMap<>(1);
hashMap.put("name", "aa");
context.setRoot(hashMap);
String expression="name ==‘aa‘";
try {
Boolean flag = (Boolean) Ognl.getValue(expression, context, context.getRoot());
System.out.println(flag);
} catch (OgnlException e) {
e.printStackTrace();
}
除了网上的那两种办法,还有其他的一些方法可以解决我遇到的问题;
hashMap.put("name", 6);
context.setRoot(hashMap);
String expression="name ==6";
下面对ognl的源码进行分析:
public static boolean isEqual(Object object1, Object object2)
{
boolean result = false;
// 1. 判断两个对象是否为同一个对象
if (object1 == object2) {
result = true;
} else {
// 2. 集合判断
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) {
for(int i = 0, icount = Array.getLength(object1); result && (i < icount); i++) {
result = isEqual(Array.get(object1, i), Array.get(object2, i));
}
}
}
} else {
// 3. 非集合判断
// 3.1 当两个值都为String类型时,就直接equals后就返回了,如果不是,则进入compareWithConversion方法;
// Check for converted equivalence first, then equals() equivalence
result = (object1 != null) && (object2 != null)&& (object1.equals(object2) || (compareWithConversion(object1, object2) == 0));
}
}
return result;
}
这个方法传入了两个值,第一个值是调用mybatis方法传入的值,这个值的类型就有很多种了,例如BigDecimal,String,Integer等等,
第二个是从mybatis的xml中读取出来的值,这个值要根据xml文件中的写法来判断了:
再根据第三个判断定位到compareWithConversion方法
public static int compareWithConversion(Object v1, Object v2)
{
int result;
if (v1 == v2) {
result = 0;
} else {
// 1
int t1 = getNumericType(v1), t2 = getNumericType(v2), type = getNumericType(t1, t2, true);
switch(type) {
case BIGINT:
result = bigIntValue(v1).compareTo(bigIntValue(v2));
break;
case BIGDEC:
result = bigDecValue(v1).compareTo(bigDecValue(v2));
break;
case NONNUMERIC:
if ((t1 == NONNUMERIC) && (t2 == NONNUMERIC)) {
if ((v1 instanceof Comparable) && v1.getClass().isAssignableFrom(v2.getClass())) {
result = ((Comparable) v1).compareTo(v2);
break;
} else {
throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and "
+ v2.getClass().getName());
}
}
// else fall through
case FLOAT:
case DOUBLE:
// 这里注意doubleValue方法,当传入的值为字母时,会抛出错误;
double dv1 = doubleValue(v1),
dv2 = doubleValue(v2);
return (dv1 == dv2) ? 0 : ((dv1 < dv2) ? -1 : 1);
default:
long lv1 = longValue(v1),
lv2 = longValue(v2);
return (lv1 == lv2) ? 0 : ((lv1 < lv2) ? -1 : 1);
}
}
return result;
}
如果属性不为数字类型,使用上边的网上的解决办法就差不多可以了
如果属性为数字类型,例如Integer,BigDecimal等等会有一个问题
当传入的值为0时,且当mybatis的xml文件中的比较为‘‘或者""时,比较的结果就是false,如下:
// 1 双引号"",传入的值为0,或者其他类型为0的值
hashMap.put("name",0);
hashMap.put("name",BigDecimal.ZERO);
String expression="name!=null and name!=\"\"";
// 2 单引号,传入的值为0,或者其他类型为0的值
hashMap.put("name",0);
hashMap.put("name",BigDecimal.ZERO);
String expression="name!=null and name!=‘‘";
解决办法:
<if test="infSrc != null and infSrc!=‘‘">AND INF_SRC = #{infSrc,jdbcType=BIGINT}</if>
// 或者
<if test="infSrc != null and infSrc!=‘‘">AND INF_SRC = #{infSrc,jdbcType=DECIMAL}</if>
这个根据自己传入值类型而定;
项目地址:https://github.com/guodayede/java-study/tree/master/ognl
标签:生效 integer except seq http efault instance tps src
原文地址:https://www.cnblogs.com/guoyuchuan/p/14106086.html