问题描述
我最近将Java 1.4应用程序迁移到Java 6环境.不幸的是,我在Oracle数据库中的BigDecimal
存储遇到了问题.总而言之,当我尝试在数据库中存储"7.65E+7"
BigDecimal值(76,500,000.00
)时,Oracle实际上存储了7,650,000.00
的值.此缺陷是由于Java 1.5中重新编写了BigDecimal
类(请参见这里).
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).
在我的代码中,BigDecimal
是使用以下代码从double
创建的:
In my code, the BigDecimal
was created from a double
using this kind of code:
BigDecimal myBD = new BigDecimal("" + someDoubleValue);
someObject.setAmount(myBD);
// Now let Hibernate persists my object in DB...
在超过99%的情况下,一切正常.除了极少数情况下,会发生上述错误.这很烦人.
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.
如果我更改先前的代码以避免使用BigDecimal
的String构造函数,那么在用例中我不会遇到错误 :
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:
BigDecimal myBD = new BigDecimal(someDoubleValue);
someObject.setAmount(myBD);
// Now let Hibernate persists my object in DB...
但是,如何确定此解决方案是处理BigDecimal
使用的正确方法?
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:
- 不使用
new BigDecimal(String)
构造函数而直接使用new BigDecimal(double)
吗? - 强制Oracle在处理
BigDecimal
时使用toPlainString()
而不是toString()
方法(在这种情况下该怎么做)? - 还有其他解决方案吗?
- 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?
环境信息:
- 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.
Edit : I've tested the same code in error but with the Oracle JDBC version 10.2.0.4.0 and the bug did not occur! The value stored was indeed 76,500,000.00
...Regarding the changelog, maybe it is related to the bug #4711863.
推荐答案
使用现代的Hibernate版本,您可以使用UserType将任何类映射到数据库字段.只需创建一个自定义UserType并将其用于将BigDecimal对象映射到数据库列即可.
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.
请参见 http://i-proving.com/space/Technologies/Hibernate/User + Types + in + Hibernate
这篇关于迁移到Java 1.4到Java 1.5+时,避免BigDecimal出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!