记一次Error querying database. Cause: java.lang.NumberFormatException: For input string: “xxx“

### Error querying database.  Cause: java.lang.NumberFormatException: For input string: "all"
### Cause: java.lang.NumberFormatException: For input string: "all"
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.5.15.jar!/:3.5.15]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:156) ~[mybatis-3.5.15.jar!/:3.5.15]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.$sw$original$selectList$od2m3g0(DefaultSqlSession.java:147) ~[mybatis-3.5.15.jar!/:3.5.15]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.$sw$original$selectList$od2m3g0$accessor$$sw$74no6b3(DefaultSqlSession.java) ~[mybatis-3.5.15.jar!/:3.5.15]
        at org.apache.ibatis.session.defaults.DefaultSqlSession$$sw$auxiliary$cug2c51.call(Unknown Source) ~[mybatis-3.5.15.jar!/:3.5.15]
        at org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstMethodsInter.intercept(InstMethodsInter.java:86) ~[skywalking-agent.jar:9.1.0]

代码

List<User> queryByStatus(@Param("filterStatus") String filterStatus);

报错的sql语句 : 单引号+单字符会被解析成char类型,而不是String类型,所以会报NumberFormatException的错误

<if test="filterStatus == 'Y' or filterStatus == 'N'">
    t.status = #{filterStatus}
</if>

问题原因

   问题的原因在于mybiatis是基于OGNL语法,在解析单引号+单字符 'Y' 时会默认是char类型,单引号+多字符 'AA' 或者双引号+单字符 "A" 解析为String类型。所以上面的报错也很好理解了,NumberFormatException 在将字符转换成数字时报错。

MyBatis 使用 OGNL(Object-Graph Navigation Language)作为其表达式语言,用于在 XML 映射文件中编写动态 SQL 查询和映射规则。在解析单引号+单字符( ‘Y’) 时,默认解析为 char 类型的原因是因为在 Java 中,单引号括起来的字符常量被认为是 char 类型的值。

具体来说,单引号括起来的内容 ‘Y’ 在 Java 中会被解释为一个 char 类型的值,而不是 String 类型。这是 Java 语言本身的特性,也是 MyBatis 在解析 OGNL 表达式时遵循的规则。

另一方面,当使用单引号+多字符 (‘AA’) 或者双引号+单字符( “A”) 时,这会被解释为 String 类型的值,因为单引号+多字符或者双引号+单字符在 Java 中被视为字符串常量。

因此,MyBatis 遵循了 Java 语言对于单引号和双引号的解释规则,以便更好地处理表达式中不同类型的常量值。这种设计使得在编写动态 SQL 查询时能够更加灵活地处理不同类型的常量,同时与 Java 语言保持一致。

解决方案

1. 外侧使用单引号,单字符使用双引号

修改后的sql语句: 采用双引号+单字符的格式

<if test='filterStatus == "Y" or filterStatus == "N"'>
    t.status = #{filterStatus}
</if>

2. 用toString()转成字符串

<if test="filterStatus == 'Y'.toString() or filterStatus == 'N'.toString()">
    t.status = #{filterStatus}
</if>

3. 加转义实体字符串引号"

<if test='filterStatus == &quot;Y&quot; or filterStatus == &quot;N&quot;'>
    t.status = #{filterStatus}
</if>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值