Хранение денежных значений как Doubles, но использование BigDecimal для вычисления значений

В настоящее время некоторые из наших объектов Hibernate используют Doubles для хранения денежных сумм, база данных хранит это значение как числовое (10,2). Расчет этих денежных двойных сумм всегда рассчитывается с использованием BigDecimals, а затем значение объекта устанавливается как двойное.

Пример:

Order order = new Order();
OrderLineItem line = new OrderLineItem(1.0, 450.00);
BigDecimal orderValue = BigDecimal.valueOf(line.getQty())
                        .multiply(BigDecimal.valueOf(line.getAmount()));
order.setOrderTotal(orderValue.setScale(2, ROUND_HALF_EVEN).doubleValue());

До сих пор это работало нормально, однако мне интересно, есть ли у этого какие-либо потенциальные риски для какой-то ошибки округления.

Мысли?


person David    schedule 26.08.2011    source источник
comment
гораздо безопаснее полностью пройти BigDecimal... Судя по тому, что вы говорите, это уже BigDecimal в БД и BigDecimal в коде вашего приложения, так почему бы просто не обновить определение сущности?   -  person Thilo    schedule 26.08.2011
comment
Я обдумываю это, однако при рефакторинге возникает волновой эффект, поскольку мы также используем проекционные запросы, которые, следовательно, ожидают, что значение будет Double vs. BigDecimal, поэтому оно не будет отображаться как ошибка компиляции, когда мы приводим от Object к Двойной. Кроме того, поскольку в настоящее время у нас нет тестового примера для всего приложения, это означало бы довольно много тестирования.   -  person David    schedule 26.08.2011
comment
Обычно в финансовом мире вы храните все значения в пенни/центах как long. Вы никогда не должны использовать значения с плавающей запятой для денег, и BigDecimal не нужен. Просто используйте longs.   -  person Luigi Plinge    schedule 26.08.2011


Ответы (1)


Пока каждая часть вашего информационного конвейера использует BigDecimal.valueOf, а BigDecimal(double) абсолютно нигде не используется, неявное округление valueOf может предотвратить худшее. Но знаете ли вы, как JPA и/или JDBC преобразуются между numeric(10,2) и double? И вы уверены, что это не изменится в будущем?

Еще один момент: valueOf и doubleValue работают с промежуточными String представлениями. В некоторых ситуациях это может быть проблемой производительности и сбора мусора.

Кроме того, примеров проблем с double достаточно — просто загляните в раздел «Похожее» справа. Или загляните в этот блог, где даже простые вещи могут привести к хаосу.

Так что ситуация немного похожа на превышение скорости: кто-то этого не делает, кто-то делает это иногда и надеется, что ничего не случится, а кто-то... Я думаю, вы понимаете.

person A.H.    schedule 09.10.2011