基于mybatis中test条件中单引号双引号的问题

网友投稿 623 2022-09-04


基于mybatis中test条件中单引号双引号的问题

目录test条件中单引号双引号问题具体原因动态sql中test的一些问题mybatis动态sql中OGNL中type=="1"和type='1'的区别解决方案

test条件中单引号双引号问题

在mybatis中test判断条件中使用单引号会报错 通常使用双引号

通常test后的判断条件写在双引号内,但是当条件中判断使用字符串时应该如下方式开发

具体原因

为单引号会被mybatis默认为字符类型,若为单字符可以使用单引号。否则会报错。

动态sql中test的一些问题

mybatis动态sql中OGNL中type=="1"和type='1'的区别

最近在mybatis中使用OGNL所遇到的坑: 一点鸡肋: type=="1"和type='1'的区别

//CountryDao.java

public interface CountryDao {

CountryDo getByType(@Param("type") String type);

}

//CountryManager.java

@Component("countryManager")

public class CountryManahttp://ger {

@Autowired

private CountryDao countryDao;

public CountryDo getByType(String type){

return countryDao.getByType(type);

}

}

mapper.xml:

//.xml

//注意写法`type=='0'`

SELECT * FROM country WHERE country_id = 2

SELECT * FROM country WHERE country_id = 3;

测试案例:

@Test

public void getByTypeTest() throws jsonProcessingException {

String type = "0";

CountryDo countryDo = countryManager.getByType(type);

ObjectMapper mapper = new ObjectMapper();

String json = mapper.writeValueAsString(countryDo);

System.out.println(json);

}

理想情况下,当type=0时返回的是country_id=2的结果

测试结果:

{"countryId":3,"country":"American Samoa","lastUpdate":"2006-02-15 04:44:00.0"}

居然返回的是country_id=3的结果

百度了才知道

原来传值进去的是String类型,而mybatis的动态sql中的OGNL表达式不会将单引号包裹的char类型的内容转成String类型,并且String类型和char类型直接比较一定是不相等的。所以输出是country_id=3的结果

解决方案

换成即可,即将单引号换成双引号

0==’'问题

一个更有趣的问题,如果将mapper.xml文件内容换成:

SELECT * FROM country WHERE country_id = 2

SELECT * FROM country WHERE country_id = 3;

测试案例不变:

@Test

public void getByTypeTest() throws JsonProcessingException {

//此时传值已经没有影响了

String type = "0";

CountryDo countryDo = countryManager.getByType(type);

ObjectMapper mapper = new ObjectMapper();

String json = mapper.writeValueAsString(countryDo);

System.out.println(json);

}

测试结果为:

{"countryId":2,"country":"Algeria","lastUpdate":"2006-02-15 04:44:00.0"}

怎么还是country_id=2的结果?,难道0==''??

查看mybatis源码发现,比如对于动态sql标签的解析:

// IfSqlNode.

@Override

public boolean apply(DynamicContext context) {

if (evaluator.evaluateBoolean(test, context.getBindings())) {

contents.apply(context);

return true;

}

return false;

}

在evaluator.evaluateBoolean方法中:

//ExpressionEvaluator.java OGNL表达式处理

public boolean evaluateBoolean(String expression, Object parameterObject) {

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;

}

当传入值为0时,因为0是Number类型,所以被转成了BiWKcQAbsbgDecimal类型,并与0作比较,test的结果为true,所以返回的是country_id=2的结果,这个说法有误。。。

再次调试,首先char ''被转成了字符String"",大概在OgnlOps.java文件的isEqual方法中的(compareWithConversion(object1, object2) == 0),点进去发现:

case NONNUMERIC:

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

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

resuWKcQAbsblt = ((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:

//v1=0, v2=""

double dv1 = doubleValue(v1),

dv2 = doubleValue(v2);

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

在doubleValue方法中:

public static double doubleValue(Object value)

throws NumberFormatException

{

if (value == null) return 0.0;

Class c = value.getClass();

if (c.getSuperclass() == Number.class) return ((Number) value).doubleValue();

if (c == Boolean.class) return ((Boolean) value).booleanValue() ? 1 : 0;

if (c == Character.class) return ((Character) value).charValue();

String s = stringValue(value, true);

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

}

坑坑坑!!!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:使用python-opencv进行人脸检测(python opencv人脸识别库)
下一篇:# yyds干货盘点 # 盘点一个pyquery库选择器提取案例
相关文章

 发表评论

暂时没有评论,来抢沙发吧~