oracle 在迁移到 Java 1.4 到 Java 1.5+ 时避免 BigDecimal 的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2622948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 20:24:06  来源:igfitidea点击:

Avoid the problem with BigDecimal when migrating to Java 1.4 to Java 1.5+

javaoraclebigdecimal

提问by Romain Linsolas

I've recently migrated a Java 1.4 application to a Java 6 environment. Unfortunately, I encountered a problem with the BigDecimalstorage in a Oracle database. To summarize, when I try to store a "7.65E+7"BigDecimal value (76,500,000.00) in the database, Oracle stores in reality the value of 7,650,000.00. This defect is due to the rewritting of the BigDecimalclass in Java 1.5 (see here).

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

In my code, the BigDecimalwas created from a doubleusing this kind of code:

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

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

In more than 99% of the cases, everything works fine. Except that in really few case, the bug mentioned above occurs. And that's quite annoying.

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

If I change the previous code to avoid the use of the String constructor of BigDecimal, then I do not encounter the bug in my uses cases:

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

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

However, how can I be sure that this solution is the correct way to handle the use of BigDecimal?

但是,我如何确定此解决方案是处理使用的正确方法BigDecimal

So my question is to know how I have to manage my BigDecimalvalues to avoid this issue:

所以我的问题是要知道我必须如何管理我的BigDecimal价值观以避免这个问题:

  • Do not use the new BigDecimal(String)constructor and use directly the new BigDecimal(double)?
  • Force Oracle to use toPlainString()instead of toString()method when dealing with BigDecimal(and in this case how to do that)?
  • Any other solution?
  • 不要使用new BigDecimal(String)构造函数,直接使用new BigDecimal(double)?
  • 强制 Oracle在处理时使用toPlainString()而不是toString()方法BigDecimal(在这种情况下如何做到这一点)?
  • 还有其他解决方案吗?

Environment information:

环境信息:

  • Java 1.6.0_14
  • Hibernate 2.1.8 (yes, it is a quite old version)
  • Oracle JDBC 9.0.2.0 and also tested with 10.2.0.3.0
  • Oracle database 10.2.0.3.0
  • 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


Edit :I've tested the same code in error but with the Oracle JDBC version 10.2.0.4.0 and the bug did notoccur! The value stored was indeed 76,500,000.00... Regarding the changelog, maybe it is related to the bug #4711863.

编辑:我已经用 Oracle JDBC 10.2.0 版错误地测试了相同的代码。41.0至没有错误不会发生!存储的值确实是76,500,000.00...关于更改日志,可能与错误 #4711863 有关。

采纳答案by Juha Syrj?l?

With modern Hibernate versions you can use UserType to map any class to a database field. Just make a custom UserType and use it to map BigDecimal object to database column.

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

See http://i-proving.com/space/Technologies/Hibernate/User+Types+in+Hibernate

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

回答by Neil Coffey

Confession: I don't personally use Hibernate, but could you just create a subclass MyBigDecimal whose toString() method calls toPlainString()?

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

I'm also not entirely sure of the merits of passing a double into the cosntructor of BigDecimal -- a double is inherently inaccurate unless the number is composed entirely of additions of powers of 2 (with range restrictions). The whole point of BigDecimal is to circumvent these restrictions on double.

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