您现在的位置是:网站首页 > 代码编程 > JAVA开发JAVA开发

【原】mybatis的if判断条件将字符串解析成了数字

不忘初心 不忘初心 2019-04-22 围观() 评论() 点赞() JAVA开发

简介:mybatis的if判断条件中,默认进行数据转换时,会将字符串解析成了数字,所以我们需要将传递参数的单双引号更换一下来解决这个问题。

mybatis可以帮我们自动映射字段,在mapper.xml文件中,我们可以不用去写jdbcType来明确指定数据类型,它会自动解析成相对应的java数据类型,每次在使用了mybatis-generator之后,出于强迫症,我还主动将默认生成的jdbcType给去掉了,一直没出过问题,今天却碰到了一个问题:

mybatis的if判断条件将字符串解析成了数字

出问题的业务场景中,需要根据不同的角色查询不同的订单数据,所以我就直接将角色ID当做参数传递进来,由于有多个角色的情况,所以直接将角色ID拼接成字符串,并用逗号分隔开。

mapper接口:

List<String> getOwnAssignedOrderNo(@Param("backendId") String backendId, @Param("role") String role);

mapper文件:

<if test="role == '1'">
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'manual_check'
</if>
<if test="role == '2' || role == '3' || role == '2,3'">
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'phone_check'
</if>
<if test="role == '1,2' || role == '1,3' || role == '1,2,3'">
    AND w.backend_id = #{backendId}
    AND (w.workflow_type = 'manual_check' OR w.workflow_type = 'phone_check')
</if>

大家注意看我这里的写法,算得上是中规中矩,role参数已经明确指定了string类型,而且在if条件中,我并没有什么特殊的写法,结果却悲剧了:

Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.NumberFormatException: For input string: "2,3"
### Cause: java.lang.NumberFormatException: For input string: "2,3"
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:434)
        ... 140 common frames omitted
Caused by: java.lang.NumberFormatException: For input string: "2,3"
        at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
        at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.lang.Double.parseDouble(Double.java:538)
        at org.apache.ibatis.ognl.OgnlOps.doubleValue(OgnlOps.java:242)
        at org.apache.ibatis.ognl.OgnlOps.compareWithConversion(OgnlOps.java:99)
        at org.apache.ibatis.ognl.OgnlOps.isEqual(OgnlOps.java:142)
        at org.apache.ibatis.ognl.OgnlOps.equal(OgnlOps.java:794)
        at org.apache.ibatis.ognl.ASTEq.getValueBody(ASTEq.java:52)
        at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
        at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
        at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494)
        at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458)
        at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44)
        at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32)
        at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34)
        at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
        at org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply(TrimSqlNode.java:55)
        at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
        at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41)
        at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
        at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
        at com.github.pagehelper.SqlUtil._processPage(SqlUtil.java:247)
        at com.github.pagehelper.SqlUtil.processPage(SqlUtil.java:229)
        at com.github.pagehelper.PageHelper.intercept(PageHelper.java:118)
        at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
        at com.sun.proxy.$Proxy349.query(Unknown Source)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
        ... 146 common frames omitted

错误非常的熟悉,类型转换异常,而且定位到了我的role参数上,一开始让我很费解,难道不能用数字类型的字符串做过参数?

以为需要对mybatis做什么特殊的配置,但是后来去其他项目比对了一下,并没有什么不一样,又跑去百度了一波,看到有人提到说没有指定jdbcType导致的,但是我这个不是字段,而是在if条件中,没办法指定jdbcType。

继续查资料,看到有大佬给了一种写法,需要对if条件中的参数做toString(),写法如下:

<if test="role == '1'.toString()">
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'manual_check'
</if>
<if test="role == '2'.toString() || role == '3'.toString() || role == '2,3'.toString()">
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'phone_check'
</if>
<if test="role == '1,2'.toString() || role == '1,3'.toString() || role == '1,2,3'.toString()">
    AND w.backend_id = #{backendId}
    AND (w.workflow_type = 'manual_check' OR w.workflow_type = 'phone_check')
</if>

不是我说,这种写法真的是很烦,判断条件简单还好说,如果复杂的条件,岂不是要写到吐血,遂继续百度之,终于找到了一种简单的写法:单引号和双引号调换一下

<if test='role == "1"'>
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'manual_check'
</if>
<if test='role == "2" || role == "3" || role == "2,3"'>
    AND w.backend_id = #{backendId}
    AND w.workflow_type = 'phone_check'
</if>
<if test='role == "1,2" || role == "1,3" || role == "1,2,3"'>
    AND w.backend_id = #{backendId}
    AND (w.workflow_type = 'manual_check' OR w.workflow_type = 'phone_check')
</if>

这样就舒服多了,不用每个if条件中都写toString(),而且问题也解决了!

此问题的出现,可以说完全是平时不注意细节所致,在项目中,我之前是有看到过同事这样写过,当时还纳闷儿为什么要将单双引换着用,强迫症的我甚至还差点儿手贱改了人家的代码,想要帮人家改邪归正,现在回想起来还真的是肤浅、无知~

方法总结:

1、如果在传参字段中,可以考虑追加jdbcType属性来指定数据类型;

2、如果在if条件中,用字符串比对的的地方少,可以直接在字符串后面跟一个toString()方法;

3、如果在if条件中,用字符串比对的地方多,直接将单引和双引调换位置;

综合考虑,尽量使用第三种写法,简单实用!

mybatis

看完文章,有任何疑问,请加入群聊一起交流!!!

很赞哦! ()

文章评论

  • 请先说点什么
    人参与,条评论

请使用电脑浏览器访问本页面,使用手机浏览器访问本页面会导致下载文件异常!!!

雨落无影

关注上方公众号,回复关键字【下载】获取下载码

用完即删,每次下载需重新获取下载码

若出现下载不了的情况,请及时联系站长进行解决

站点信息

  • 网站程序:spring + freemarker
  • 主题模板:《今夕何夕》
  • 文章统计:篇文章
  • 标签管理标签云
  • 微信公众号:扫描二维码,关注我们