Избегайте проблемы с BigDecimal при переходе с Java 1.4 на Java 1.5+ - PullRequest
3 голосов
/ 12 апреля 2010

Я недавно перенес приложение Java 1.4 в среду Java 6. К сожалению, я столкнулся с проблемой хранения BigDecimal в базе данных Oracle. В итоге, когда я пытаюсь сохранить значение "7.65E+7" BigDecimal (76,500,000.00) в базе данных, Oracle в действительности сохраняет значение 7,650,000.00. Этот дефект связан с переписыванием класса BigDecimal в Java 1.5 (см. здесь ).

В моем коде BigDecimal был создан из double с использованием этого вида кода:

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

В более чем 99% случаев все работает нормально. За исключением того, что в очень немногих случаях упоминается вышеупомянутая ошибка. И это довольно раздражает.

Если я изменю предыдущий код, чтобы избежать использования конструктора String BigDecimal, я не столкнусь с ошибкой в моих случаях использования :

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

Однако, как я могу быть уверен, что это решение является правильным способом обработки BigDecimal?

Поэтому мой вопрос состоит в том, чтобы знать, как мне управлять значениями BigDecimal, чтобы избежать этой проблемы:

  • Не используйте конструктор new BigDecimal(String) и используйте непосредственно new BigDecimal(double)?
  • Заставить Oracle использовать toPlainString() вместо toString() метода при работе с BigDecimal (и в этом случае как это сделать)?
  • Любое другое решение?

Информация об окружающей среде:

  • 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 ... Что касается changelog , возможно, это связано с ошибкой # 4711863.

Ответы [ 2 ]

3 голосов
/ 12 апреля 2010

В современных версиях Hibernate вы можете использовать UserType для сопоставления любого класса с полем базы данных. Просто создайте пользовательский тип пользователя и используйте его для сопоставления объекта BigDecimal со столбцом базы данных.

См. http://i -proving.com / space / Technologies / Hibernate / Пользователь + Типы + in + Hibernate

2 голосов
/ 12 апреля 2010

Исповедь: я лично не использую Hibernate, но не могли бы вы просто создать подкласс MyBigDecimal, чей метод toString () вызывает toPlainString ()?

Я также не совсем уверен в достоинствах передачи двойного числа в кентруктор BigDecimal - двойное по своей сути неточно, если число не состоит полностью из сложения степеней 2 (с ограничениями по дальности). Весь смысл BigDecimal в том, чтобы обойти эти ограничения в два раза.

...