代码之家  ›  专栏  ›  技术社区  ›  Elie

休眠和货币精度

  •  4
  • Elie  · 技术社区  · 15 年前

    我有一个休眠映射,如下所示:

    <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
    

    我试着把管理员的类型改成双倍,但也没用。问题是,Hibernate确实正确地执行了插入操作,将来的select语句可以返回当前的一组值,但是这个错误阻止了我进一步处理这个发票。

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

    对于如何解决这一问题的任何帮助都将不胜感激。

    5 回复  |  直到 12 年前
        1
  •  5
  •   Phil    15 年前

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

        2
  •  12
  •   Bill the Lizard Drew    12 年前

    使用浮动或双重兑换货币是绝对不可接受的,甚至可能是非法的(如违反法律或至少违反规定)。这需要修正,然后错误就会消失。float的精度有限,不能精确地表示大多数小数。

    For money, always, ALWAYS use BigDecimal.

        3
  •  1
  •   OscarRyz    15 年前

    您是否尝试分配类型?

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

    看来问题在于数据的准确性。有时当你有1.266666666…值被截断。

    您也可以尝试在尝试插入之前将其舍入。

    见: http://bugs.mysql.com/bug.php?id=7829

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

        4
  •  0
  •   Elie    15 年前

    最后我没有使用float、bigdecimal或double。我回到客户那里,他们同意放下硬币,因为不管怎样,客户总是要收整数,所以没必要把硬币存起来。但是,我仍然需要弄清楚如何正确地存储货币,因为这很可能会再次出现。

        5
  •  0
  •   duffymo    15 年前

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