4.Mybatis里注入0的判断

[转]mybatis if test非空判断数字0为什么是false
原文地址:http://blog.51cto.com/wangguangshuo/1944531

今天工作中发现一个Long类型的参数没有传到sql中去,在sql xml配置文件中是使用if test标签判断:

xxxxx

通过debug发现参数中的version是有值的,但出来的sql语句就没有这个version

网上查了一些有不少同样这样的问题,大致解决办法分两种:

1、去掉空字符串判断

     <if test="version != null">xxxxx</if>

2、添加0值判断

     <if test="version != null and version != '' or version == 0">xxxxx</if>

这两种方法都是可以的,在我看来是这样,如果这个version类型和我的情况一样,是包装类型而不是基本数据类型的话,第一种就足够了,而且更贴近实际,因为包装类型除了有值的情况就是null,不会为""空字符串的,String类型不在我讨论的范围内,标题已经说了是数字0,况且如果是String的话就不会有这个问题了。

知道了怎么解决这个问题,那就想知道为什么这个问题会出现,当然要查看mybatis的源码了,

sql语句是通过获取BoundSql来的(网上查看mybatis层次结构),这个是通过方法getBoundSql(),这个方法定义在一个接口SqlSource,它有五个实现,从命名上看应该是找DynamicSqlSource,

暂时缺少图片

if判断的这种属于动态的sql所以直接找它了

这里面有句:rootSqlNode.apply(content);这个是添加动态sql 的,点进去查看

apply也是在一个接口里,查看实现,各种和标签有关的命名实现,这个标签是if当然就是找IfSqlNode了,它里面的实现是通过evaluator.evaluateBoolean()方法判断的,点进去继续看

发现一行重要的代码:

if(value instanceof Number) return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);

现在真相大白了,不管是Inteter还是Long,只要是值为0,都会判断为false

真的很抱歉,上面的分析错了,早上来了之后有四个浏览,立刻隐藏了这篇文章准备修改,希望那四位网友能再看到更正,上面的分析是在昨天晚上下班后,现在我又看了一遍昨天打开的源码:

上面的value其实是test后面的表达式的返回值,而不是传入的version参数,test后面的表达式如果只写一个0的话就会走上面的if判断,直接返回false,但眼前的情况是version为0,test后面的表达式就是:0 != null and 0 != ‘’,这个表达式是由org.apache.ibatis.scripting.xmltags.OgnlCache类的getValue(String expression,Objec root)方法得来,下载了ognl源码包关联之后从新走的debug追踪了一下,还是从上面IfSqlNode中的apply方法判断说起:

(DynamicContext context) {
(.evaluateBoolean(context.getBindings())) {
.apply(context)}
}

猜你喜欢

转载自blog.csdn.net/weixin_42137448/article/details/88717613