2011-04-20 4 views
5

mam tę kolumnę w moim Oracle 11g odwzorowany jako numer (21,20), który jest odwzorowany w Hibernate jako:Hibernate utrata precyzji wyników podczas mapowania numeru (22,21) do BigDecimal

@Column(name = "PESO", precision = 21, scale = 20, nullable = false) 
public BigDecimal getWeight() { 
    return weight; 
} 

Dla konkretnego rekordu, dla którego wartość kolumny wynosi 0,443, otrzymuję BigDecimal, którego wartość wynosi 0,49299999999. Wydaje się, że gdzieś tam jest utrata dokładności należytym (być może) do podwójnego lub Float konwersji, ale nie mogłem śledzić go za pomocą prostego testu jednostkowego jak ten:

Double d = new Double("0.493"); 
System.out.println((d)); 

dowolny wariant tego kodeksu za pomocą Float, BigDecimal i różnych konstruktorów daje taki sam wynik: "0.493" ... Jakąkolwiek wskazówkę, jak mam odwzorować kolumnę, aby uniknąć takich problemów? Używam Hibernacja 3.5.6, z adnotacjami WZP i Hibernacja API (czyli sesja i nie EntityManager)

+0

wydaje się, że to nie był błąd hibernacji ... Jest to całkowicie na SquirrelSql, który wyświetla 0.493 dla wartości 0.49299999999 ... Wartość zawsze była, zarówno w pliku "źródło", zarówno w bazie danych , jak raporty SqlDeveloper. –

Odpowiedz

3

Jest to wynikiem inicjowanie BigDecimal od double:

System.out.println(String.format("%21.20f", new BigDecimal(0.493)); 
// Prints 0,49299999999999999378 

Więc, kiedy to zainicjowany BigDecimal sposób jest zapisywany w bazie danych, generuje niedokładną wartość, która jest poprawnie ładowana później.

Jeśli BigDecimal jest zainicjowany przez ciąg znaków lub jeśli wartość jest ustawiona bezpośrednio w Javie wszystko działa poprawnie.

+0

dzięki za przykład, prawdopodobnie część "% 21.20" robi jakąś sztuczkę, ponieważ System.out.println (String.format ("% f", nowy BigDecimal (0.493))); drukuj prawie dobrze -> "0,493000". To jednak nie było moje :-) –