2011-08-26 82 views
2

目前我们的一些Hibernate的实体使用双打存储货币金额,数据库存储这个值作为一个数字(10,2)。这些货币双重金额的计算总是使用BigDecimals计算,然后将实体值设置为double。存储货币值双打,但使用的BigDecimal计算值

例子:

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()); 

这一直很好,到目前为止,但我不知道是否该有某种形式的舍入误差的任何潜在风险。

想法?

+1

更安全去的BigDecimal一路......从你说的时候,就已经是BigDecimal的在数据库中,并BigDecimal的在应用程序代码,所以为什么不更新实体的定义是什么? – Thilo

+0

我正在考虑这一点,但是有一个连锁反应,如果我们重构,因为我们还可以使用其因此期待值是一个双对BigDecimal的投影查询,所以它不会显示为一个编译错误,因为我们从Object强制加倍。另外,由于我们目前没有整个应用程序的测试用例,这意味着相当多的测试。 – David

+1

通常在金融世界中,您将所有价值以便士/美分作为“长”存储。您绝对不应该使用浮点值来获取金钱,并且BigDecimal是不必要的。只要使用'长'。 –

回答

2

只要每一件你的信息管道使用BigDecimal.valueOfBigDecimal(double)用于绝对无处那么valueOf隐式舍入可能会阻止最坏的打算。但是,你真的知道JPA和/或JDBC numeric(10,2)double之间如何转化?你确定,这在未来不会改变吗?

另一点:valueOfdoubleValue使用中间String表示法。在某些情况下,这可能是性能和垃圾收集问题。

而且这也有足够的例子与double问题 - 简单地看向右侧的“相关”部分。或者看看这个blog即使简单的东西可以破坏浩劫。

所以情况有点像超速:有些不这样做,有时候有些做出来,希望什么都不会发生,有些......我觉得你得到它。