从 Java 1.4 迁移到 Java 1.5+ 时避免 BigDecimal 的问题
-
26-09-2019 - |
题
我最近将 Java 1.4 应用程序迁移到 Java 6 环境。不幸的是,我遇到了一个问题 BigDecimal
存储在Oracle数据库中。总而言之,当我尝试存储 "7.65E+7"
大十进制值 (76,500,000.00
)在数据库中,Oracle 实际上存储了以下值 7,650,000.00
. 。这个缺陷是由于重写了 BigDecimal
Java 1.5 中的类(参见 这里).
在我的代码中, BigDecimal
是从一个创建的 double
使用这种代码:
BigDecimal myBD = new BigDecimal("" + someDoubleValue);
someObject.setAmount(myBD);
// Now let Hibernate persists my object in DB...
在超过 99% 的情况下,一切正常。除了极少数情况下,会发生上述错误。这很烦人。
如果我更改前面的代码以避免使用 String 构造函数 BigDecimal
, ,那么我就没有遇到这个bug 在我的用例中:
BigDecimal myBD = new BigDecimal(someDoubleValue);
someObject.setAmount(myBD);
// Now let Hibernate persists my object in DB...
但是,我如何确定该解决方案是处理使用的正确方法 BigDecimal
?
所以我的问题是知道我必须如何管理我的 BigDecimal
避免此问题的值:
- 不要使用
new BigDecimal(String)
构造函数并直接使用new BigDecimal(double)
? - 强制 Oracle 使用
toPlainString()
代替toString()
处理时的方法BigDecimal
(在这种情况下该怎么做)? - 还有其他解决方案吗?
环境信息:
- Java 1.6.0_14
- Hibernate 2.1.8(是的,这是一个相当旧的版本)
- Oracle JDBC 9.0.2.0 并使用 10.2.0.3.0 进行了测试
- Oracle数据库10.2.0.3.0
编辑 : 我已经使用 Oracle JDBC 版本 10.2.0 测试了相同的错误代码。4.0 并且该错误确实发生了 不是 发生!存储的值确实是 76,500,000.00
...关于 变更日志, ,可能与错误#4711863有关。
解决方案
使用现代 Hibernate 版本,您可以使用 UserType 将任何类映射到数据库字段。只需创建一个自定义 UserType 并使用它将 BigDecimal 对象映射到数据库列。
看 http://i-proving.com/space/Technologies/Hibernate/User+Types+in+Hibernate
其他提示
忏悔:我个人不使用 Hibernate,但是您可以创建一个子类 MyBigDecimal,其 toString() 方法调用 toPlainString() 吗?
我也不完全确定将双精度数传递给 BigDecimal 的构造函数的优点——双精度数本质上是不准确的,除非该数字完全由 2 的幂相加组成(有范围限制)。BigDecimal 的全部目的是规避这些对 double 的限制。