我将采用激进的方式,不使用BigDecimal。
这是一篇很棒的文章https://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/
来自这里的想法。
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
testConstructors();
testEqualsAndCompare();
testArithmetic();
}
private static void testEqualsAndCompare() {
final BigDecimal zero = new BigDecimal("0.0");
final BigDecimal zerozero = new BigDecimal("0.00");
boolean zerosAreEqual = zero.equals(zerozero);
boolean zerosAreEqual2 = zerozero.equals(zero);
System.out.println("zerosAreEqual: " + zerosAreEqual + " " + zerosAreEqual2);
int zerosCompare = zero.compareTo(zerozero);
int zerosCompare2 = zerozero.compareTo(zero);
System.out.println("zerosCompare: " + zerosCompare + " " + zerosCompare2);
}
private static void testArithmetic() {
try {
BigDecimal value = new BigDecimal(1);
value = value.divide(new BigDecimal(3));
System.out.println(value);
} catch (ArithmeticException e) {
System.out.println("Failed to devide. " + e.getMessage());
}
}
private static void testConstructors() {
double doubleValue = 35.7;
BigDecimal fromDouble = new BigDecimal(doubleValue);
BigDecimal fromString = new BigDecimal("35.7");
boolean decimalsEqual = fromDouble.equals(fromString);
boolean decimalsEqual2 = fromString.equals(fromDouble);
System.out.println("From double: " + fromDouble);
System.out.println("decimalsEqual: " + decimalsEqual + " " + decimalsEqual2);
}
}
它打印
From double: 35.7000000000000028421709430404007434844970703125
decimalsEqual: false false
zerosAreEqual: false false
zerosCompare: 0 0
Failed to devide. Non-terminating decimal expansion; no exact representable decimal result.
如何将BigDecimal存储到数据库中?竟然会以double值的形式存储吗?至少,如果我在没有任何高级配置的情况下使用mongoDb,它将把BigDecimal.TEN存储为1E1。
可能的解决方案是什么?
我想到一个方法-在Java中使用String将BigDecimal作为字符串存储到数据库中。您可以进行验证,例如@NotNull,@Min(10)等...然后,您可以在更新或保存时使用触发器来检查当前字符串是否是所需数字。不过,mongo没有触发器。
Mongodb触发器函数调用是否有内置方式?
我遇到了一个有趣的缺点 - {{link2:Swagger定义中的BigDecimal作为字符串}}
我需要生成swagger,这样我们的前端团队就能理解我传递给他们的数字是以字符串形式呈现的。例如,DateTime以字符串形式呈现。
我在上面的文章中读到了另一个很酷的解决方案......使用long存储精确数字。
标准的long值可以存储美国国债的当前价值(以美分而非美元计算)6477次,而不会发生溢出。更重要的是:它是整数类型,而不是浮点类型。这使得它更易于处理和准确,并且保证了行为的可靠性。
更新
https://stackoverflow.com/a/27978223/4587961
也许在未来,MongoDb会增加对BigDecimal的支持。
https://jira.mongodb.org/browse/SERVER-1393
看起来3.3.8已经完成了这个功能。
这是第二种方法的示例。使用缩放。
http://www.technology-ebay.de/the-teams/mobile-de/blog/mapping-bigdecimals-with-morphia-for-mongodb.html