休眠和货币精确度

时间:2008-12-30 02:42:03

标签: java hibernate types

我有一个hibernate映射如下:

<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>    

其中InvoiceTVO的变量定义为:

private int id;
private Date date;
private int customerId;
private int schoolId;
private float bookFee;
private float adminFee;
private float totalFee;

当我在此表上插入时,出现以下错误:

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

我尝试将adminFee的类型更改为double,但这也无效。问题是,Hibernate确实正确地执行了插入操作,并且将来的select语句可以返回当前的值集,但是这个错误阻止我对此发票进行进一步处理。

字段bookFee,adminFee和totalFee都应该是货币。它们在MySQL数据库中定义为十进制(5,2)。

如何解决这个问题的任何帮助将不胜感激。

5 个答案:

答案 0 :(得分:12)

使用浮动或双人换钱是绝对不可接受的,甚至可能是非法的(如违反法律或至少是法规)。这需要修复,然后错误将消失。 float的精度有限,根本无法准确表示大多数小数部分。

For money, always, ALWAYS use BigDecimal.

答案 1 :(得分:5)

我会使用整数类型(int,long)。只要你能避免溢出,就不会有任何有趣的问题。

答案 2 :(得分:1)

您是否尝试过分配类型?

<property name="adminFee" column="ADMIN_FEE" type="float"/>

似乎问题在于数据的精确性。有时你有1.26666666666 ...值被截断。

您也可以在尝试插入之前尝试对其进行舍入。

请参阅:http://bugs.mysql.com/bug.php?id=7829

另外,看看这是否有帮助: http://www.ibm.com/developerworks/java/library/j-jtp0114/

答案 3 :(得分:0)

我最终没有使用float,BigDecimal或double。我回到了客户端,他们同意放弃便士,因为客户总是收取圆润的数字,所以没有必要存放便士。但是,我仍然需要弄清楚如何正确存储货币,因为这可能会再次出现。

答案 4 :(得分:0)

自定义Hibernate映射和类定义将是一个很好的方法。