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
Avoid the problem with BigDecimal when migrating to Java 1.4 to Java 1.5+
提问by Romain Linsolas
I've recently migrated a Java 1.4 application to a Java 6 environment. Unfortunately, I encountered a problem with the BigDecimal
storage 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 BigDecimal
class 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 BigDecimal
was created from a double
using this kind of code:
在我的代码中,BigDecimal
是double
使用这种代码从 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 BigDecimal
values to avoid this issue:
所以我的问题是要知道我必须如何管理我的BigDecimal
价值观以避免这个问题:
- Do not use the
new BigDecimal(String)
constructor and use directly thenew BigDecimal(double)
? - Force Oracle to use
toPlainString()
instead oftoString()
method when dealing withBigDecimal
(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 的限制。