Bad format for BigDecimal ‘1,100.00‘ in column 1 错误

博客讲述订单信息导出时,选择某时间段数据报错的问题。错误信息显示数字转换异常,经排查发现是SQL中使用的FORMAT函数返回以逗号分隔的字符串,导致MyBatis转换出错。一般不报错是因字段较小时可能无逗号。解决办法是将FORMAT函数替换成ROUND。

问题场景:
订单信息导出时,在选择某一时间段数据时会报错,但是一般不报错。

错误信息:
org.springframework.dao.TransientDataAccessResourceException: Error attempting to get column ‘FORMAT(spd.cost_price/100,2)’ from result set. Cause: java.sql.SQLException: Bad format for BigDecimal ‘1,100.00’ in column 1.
; ]; Bad format for BigDecimal ‘1,100.00’ in column 1.; nested exception is java.sql.SQLException: Bad format for BigDecimal ‘1,100.00’ in column 1.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:110)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)

错误原因分析:
查看报错信息为SQLException,但是本地运行sql并没有问题。于是进一步查看报错信息Bad format for BigDecimal分析可能是类型没有对应上导致数字转换出错,但是查看mybatis转化的对象字段类型是bigdecimal,与数据库的字段类型一致。在仔细看报错信息‘1,087.50’,第一眼感觉有点怪怪的但是没有发现问题。只好找到对应的sql进行排查,在看sql的过程中看到了使用了FORMAT作为四舍五入的函数。

查询FORMAT函数使用方法后找到问题的关键是:FORMAT函数会四舍五入之后返回一个以逗号分隔的字符串,所以导致出现了‘1,087.50’这样的数字,乍一看没有问题,事实上这个已经是字符串了,这才导致了mybatis转换时出现了异常。一般不报错因为这个字段一般比较小,导致这个字段不一定含有逗号,只要没有逗号,最终都会进行类型转换。

解决办法:
把FORMAT函数替换成ROUND即可 ,完美解决

Java中,将 `BigDecimal` 类型的数值(如 `100.00`)转换为 `long` 类型时,需要特别注意精度问题。由于 `BigDecimal` 可以表示高精度的十进制数值,直接转换时应确保数值是整数形式,或者明确接受小数部分被截断的风险。 ### 使用 `longValueExact()` 方法进行精确转换 为了确保转换过程中不会丢失精度,推荐使用 `BigDecimal` 提供的 `longValueExact()` 方法。该方法会在数值包含小数部分时抛出 `ArithmeticException` 异常,从而避免静默的数据丢失。 ```java import java.math.BigDecimal; public class BigDecimalToLong { public static void main(String[] args) { BigDecimal decimalValue = new BigDecimal("100.00"); try { long longValue = decimalValue.longValueExact(); System.out.println("Converted long value: " + longValue); } catch (ArithmeticException e) { System.out.println("The value has a non-zero fractional part and cannot be converted exactly to long."); } } } ``` 此方法适用于需要确保数值为整数的场景,例如金融计算中对金额的转换操作[^1]。 ### 使用 `longValue()` 方法进行截断转换 如果允许小数部分被截断,可以使用 `longValue()` 方法。该方法会直接丢弃小数部分,仅保留整数部分。 ```java import java.math.BigDecimal; public class BigDecimalToLongTruncated { public static void main(String[] args) { BigDecimal decimalValue = new BigDecimal("100.99"); long longValue = decimalValue.longValue(); System.out.println("Truncated long value: " + longValue); } } ``` 上述代码将输出 `100`,因为 `.99` 被截断。这种方式适用于不需要保留小数部分的场景,但需谨慎使用以避免精度丢失问题[^2]。 ### 注意事项 - 在构造 `BigDecimal` 对象时,应优先使用 `String` 类型的构造方法,以避免使用 `double` 类型构造时可能引入的精度误差。 - 在涉及金融或高精度计算的场景中,应优先使用 `longValueExact()` 方法,以确保数据的完整性和准确性[^1]。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值