Как использовать тип данных money в Java, SQL, ORM - PullRequest
19 голосов
/ 28 января 2011

Каковы лучшие практики использования типа данных money в приложении Java? Деньги должны быть в двойной переменной? Что насчет округления, валют и тд. Есть специальные библиотеки для этого? А как насчет ORM и SQL в самых популярных базах данных. Как я знаю не во всех движках SQL есть тип данных Money. В таком случае следует использовать NUMERIC(15,2), DECIMAL(15,2) или тип данных REAL?

Ответы [ 4 ]

21 голосов
/ 28 января 2011

Каковы лучшие практики использования типа данных money в приложении Java?

Использовать BigDecimal. Использование любого примитива рано или поздно приведет к возникновению проблем точности.

А как насчет ORM и SQL в самых популярных базах данных?

Hibernate (и, вероятно, все остальные) может нормально работать с BigDecimal. И это переводится в соответствующий тип базы данных, который обычно является DECIMAL.

18 голосов
/ 28 января 2011

Вы должны использовать BigDecimal для представления денежных значений.

Из Bloch, J., Effective Java, 2nd ed, Item 48:

Типы float и double особенно плохо подходят для денежных расчетов, поскольку невозможно точно представить 0,1 (или любую другую отрицательную степень десяти) как float или double.

Например, предположим, у вас есть 1,03 доллара, а вы тратите 42c.Сколько у вас осталось денег?

System.out.println(1.03 - .42);

распечатывает 0.6100000000000001.

Правильный способ решения этой проблемы - использовать BigDecimal, int или longдля денежных расчетов.

Для SQL я использую NUMERIC(19,2).

4 голосов
/ 28 января 2011

В кругах разработчиков, как правило, рекомендуется использовать BigDecimal для денег в Java. Это не значит, что это всегда лучше, чем использовать двойное ИМХО, но я бы посоветовал вам начать с BigDecimal.

Для SQL я предлагаю использовать соответствующий тип NUMERIC или DECIMAL для BigDecimal и REAL для double.

Стоит отметить, что все инвестиционные банки и торговые дома, на которых я работал, использовали double с округлением на деньги (в C ++ и Java). И наоборот, я никогда не видел, чтобы использовался BigDecimal, но я видел NUMERIC, используемый в базах данных. Для целей бухгалтерского учета используйте BigDecimal.

0 голосов
/ 14 февраля 2019

Не используйте BigDecimal для хранения номеров прецедентов.

https://stackoverflow.com/a/54681006/4587961

Теперь несколько примеров, почему.

double doubleValue = 35.7;
BigDecimal fromDouble = new BigDecimal(doubleValue);
BigDecimal fromString = new BigDecimal("35.7");

boolean decimalsEqual = fromDouble.equals(fromString);

System.out.println("From double: " + fromDouble + " " + fromString.stripTrailingZeros().toPlainString());
System.out.println("decimalsEqual: " + decimalsEqual");

печать

From double: 35.7000000000000028421709430404007434844970703125 35.7
decimalsEqual: false

Также у меня был иссе, когда большой десятичный знак хранился как двойной в монго. Затем был вызван конструктор BigDecimal с двойным аргументом. Противопоставление истинной практики - создание большого десятичного числа из двойного.

Подробнее и примеры в ссылке выше!

...