3

我最近将 Java 1.4 应用程序迁移到 Java 6 环境。不幸的是,我遇到了BigDecimalOracle 数据库中的存储问题。总而言之,当我尝试在数据库中存储"7.65E+7"BigDecimal 值 ( 76,500,000.00) 时,Oracle 实际上存储了7,650,000.00. 这个缺陷是由于BigDecimal在 Java 1.5 中重写了类(参见此处)。

在我的代码中,BigDecimaldouble使用这种代码创建的:

BigDecimal myBD = new BigDecimal("" + someDoubleValue);
someObject.setAmount(myBD);
// Now let Hibernate persists my object in DB...

在超过 99% 的情况下,一切正常。除了在极少数情况下,会发生上述错误。这很烦人。

如果我更改前面的代码以避免使用 String 的构造函数BigDecimal,那么我不会在我的用例中遇到错误:

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...关于changelog,可能与错误 #4711863 有关。

4

2 回答 2

3

使用现代 Hibernate 版本,您可以使用 UserType 将任何类映射到数据库字段。只需制作一个自定义 UserType 并使用它将 BigDecimal 对象映射到数据库列。

请参阅http://i-proving.com/space/Technologies/Hibernate/User+Types+in+Hibernate

于 2010-04-12T15:45:14.080 回答
2

忏悔:我个人不使用Hibernate,但你能创建一个子类MyBigDecimal,它的toString()方法调用toPlainString()吗?

我也不完全确定将双精度传递给 BigDecimal 的构造函数的优点——双精度本质上是不准确的,除非该数字完全由 2 的幂的加法组成(有范围限制)。BigDecimal 的全部意义在于规避这些对 double 的限制。

于 2010-04-12T15:03:04.977 回答