Vermeiden Sie das problem mit BigDecimal bei der Migration von Java 1.4 auf Java 1.5+
Ich habe vor kurzem migriert eine Java 1.4-Anwendung zu einem Java-6-Umgebung. Leider stieß ich auf ein problem mit der BigDecimal
Speicherung in einer Oracle-Datenbank. Um zusammenzufassen, wenn ich versuche zu speichern, die "7.65E+7"
BigDecimal-Wert (76,500,000.00
) in die Datenbank, Oracle speichert in der Realität ist der Wert von 7,650,000.00
. Dieser Mangel ist durch die nach dem umschreiben des von der BigDecimal
Klasse in Java 1.5 (siehe hier).
In meinem code, die BigDecimal
entstand aus einem double
mit dieser Art von code:
BigDecimal myBD = new BigDecimal("" + someDoubleValue);
someObject.setAmount(myBD);
//Now let Hibernate persists my object in DB...
In mehr als 99% der Fälle funktioniert alles einwandfrei. Außer dass man wirklich einige Fälle vor, die oben genannten Fehler Auftritt. Und das ist ziemlich nervig.
Wenn ich den vorherigen code ändern, um die Verwendung der String-Konstruktor BigDecimal
ist, dann weiß ich nicht auftreten, der Fehler in meine Anwendungsfälle:
BigDecimal myBD = new BigDecimal(someDoubleValue);
someObject.setAmount(myBD);
//Now let Hibernate persists my object in DB...
Aber wie kann ich sicher sein, dass diese Lösung die richtige Art und Weise zu behandeln, die Verwendung von BigDecimal
?
Also meine Frage ist zu wissen, wie ich manage meine BigDecimal
Werte um dieses Problem zu vermeiden:
- Verwenden Sie nicht die
new BigDecimal(String)
Konstruktor und die Nutzung direkt dernew BigDecimal(double)
? - Kraft Oracle zu verwenden
toPlainString()
statttoString()
Methode beim Umgang mitBigDecimal
(und in diesem Fall, wie das geht)? - Eine andere Lösung?
Umgebung Informationen:
- Java 1.6.0_14
- Hibernate 2.1.8 (ja, es ist eine ziemlich alte version)
- Oracle-JDBC-9.0.2.0 und auch getestet mit 10.2.0.3.0
- Oracle-Datenbank 10.2.0.3.0
Edit : getestet hab ich den gleichen code in Fehler, aber mit der Oracle-JDBC version 10.2.0.4.0 und der Fehler trat nicht auftreten! Der gespeicherte Wert war in der Tat 76,500,000.00
...
In Bezug auf die changelog, vielleicht ist es im Zusammenhang mit dem bug #4711863.
- Autsch, böse Verhalten zu ändern. Ich werde daran denken das das nächste mal sagen Sie Java geht durch Reifen, die auf rückwärts-Kompatibilität.
- ja, in der Tat, aber Sie zeigen in dem angegebenen link, dass
The JSR 13 expert group was aware of the possible compatability issues when changing the definition of toString; however, changing its definition was deemed necessary to reap the other benefits of the JSR.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Mit modernen Hibernate-Versionen, die Sie verwenden können, UserType abbilden jeder Klasse auf eine Datenbank-Feld. Machen Sie einfach eine benutzerdefinierte UserType und es verwenden, um anzeigen BigDecimal-Objekt Spalte in der Datenbank.
Sehen http://i-proving.com/space/Technologies/Hibernate/User+Arten+in+Ruhezustand
Geständnis: ich persönlich nicht verwenden, Hibernate, aber könnten Sie einfach erstellen Sie eine Unterklasse MyBigDecimal deren toString () - Methode ruft toPlainString()?
Ich bin auch nicht ganz sicher, die Verdienste der übergabe eines double in der cosntructor von BigDecimal -- ein double ist von Natur aus ungenau, es sei denn, die Zahl ist zusammengesetzt Ergänzungen von Potenzen von 2 (mit range-Einschränkungen). Der ganze Punkt von BigDecimal ist die Umgehung dieser Restriktionen auf das doppelte.