java 休眠和货币精度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/399401/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate and currency precision
提问by Elie
I have a hibernate mapping as follows:
我有一个休眠映射如下:
<hibernate-mapping>
<class name="kochman.elie.data.types.InvoiceTVO" table="INVOICE">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="date" column="INVOICE_DATE"/>
<property name="customerId" column="CUSTOMER_ID"/>
<property name="schoolId" column="SCHOOL_ID"/>
<property name="bookFee" column="BOOK_FEE"/>
<property name="adminFee" column="ADMIN_FEE"/>
<property name="totalFee" column="TOTAL_FEE"/>
</class>
</hibernate-mapping>
where InvoiceTVO has variables defined as:
其中 InvoiceTVO 的变量定义为:
private int id;
private Date date;
private int customerId;
private int schoolId;
private float bookFee;
private float adminFee;
private float totalFee;
When I do an insert on this table, I get the following error:
当我在这个表上插入时,我收到以下错误:
Hibernate: insert into INVOICE (INVOICE_DATE, CUSTOMER_ID, SCHOOL_ID, BOOK_FEE, ADMIN_FEE, TOTAL_FEE, ID) values (?, ?, ?, ?, ?, ?, ?)
50156 [AWT-EventQueue-0] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 22001
50156 [AWT-EventQueue-0] ERROR org.hibernate.util.JDBCExceptionReporter - Data truncation: Data truncated for column 'ADMIN_FEE' at row 1
50156 [AWT-EventQueue-0] ERROR org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session
I tried changing the type of adminFee to double, and that didn't work either. The problem is, Hibernate did actually perform the insert properly, and future select statements work to return the current set of values, but this error prevents me from doing further processing on this invoice.
我尝试将 adminFee 的类型更改为双倍,但也没有用。问题是,Hibernate 实际上确实正确地执行了插入,并且未来的 select 语句可以返回当前的一组值,但是这个错误阻止了我对这张发票做进一步的处理。
The fields bookFee, adminFee, and totalFee are all supposed to be currencies. They are defined in the MySQL database as decimal(5,2).
字段 bookFee、adminFee 和 totalFee 都应该是货币。它们在 MySQL 数据库中定义为十进制 (5,2)。
Any help in how to resolve this would be greatly appreciated.
任何有关如何解决此问题的帮助将不胜感激。
回答by Michael Borgwardt
Using float or double for money is absolutely inacceptable and may even be illegal (as in, breaking laws or at least regulations). That needs to be fixed, then the error will disappear. float has limited precision and cannot accurately represent most decimal fractions at all.
使用浮动或双倍货币是绝对不能接受的,甚至可能是非法的(例如,违反法律或至少是法规)。这需要修复,然后错误就会消失。float 的精度有限,根本无法准确表示大多数小数。
回答by Phil
I would use an integer type (int, long). Never any funny issues with those as long you can avoid overflows.
我会使用整数类型(int,long)。只要您可以避免溢出,就不会遇到任何有趣的问题。
回答by OscarRyz
Have you tried assigning the type?
您是否尝试过分配类型?
<property name="adminFee" column="ADMIN_FEE" type="float"/>
It seems the problem is with the precision of the data. Sometime when you have 1.26666666666... the value is truncated.
问题似乎出在数据的精度上。有时当你有 1.26666666666 时......该值被截断。
You can also try to round it before attempting the insert.
您也可以在尝试插入之前尝试将其四舍五入。
See: http://bugs.mysql.com/bug.php?id=7829
参见:http: //bugs.mysql.com/bug.php?id=7829
Also, see if this helps: http://www.ibm.com/developerworks/java/library/j-jtp0114/
另外,看看这是否有帮助:http: //www.ibm.com/developerworks/java/library/j-jtp0114/
回答by Elie
I ended up not using float, BigDecimal, or double. I went back to the client, and they agreed to drop the pennies, since the customer is always charged the rounded figure anyways, so there's no need to store the pennies. However, I will still need to figure out how to store the currencies properly, since this will likely come up again.
我最终没有使用 float、BigDecimal 或 double。我回到客户那里,他们同意放弃这些便士,因为无论如何总是向客户收取四舍五入的费用,因此无需存储便士。但是,我仍然需要弄清楚如何正确存储货币,因为这可能会再次出现。
回答by duffymo
A custom Hibernate mapping and a class definition would be a good way to go.
自定义 Hibernate 映射和类定义将是一个好方法。

