Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate and currency precision

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:

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.

The fields bookFee, adminFee, and totalFee are all supposed to be currencies. They are defined in the MySQL database as decimal(5,2).

Any help in how to resolve this would be greatly appreciated.

like image 249
Elie Avatar asked Dec 30 '08 02:12

Elie


1 Answers

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.

For money, always, ALWAYS use BigDecimal.

like image 126
Michael Borgwardt Avatar answered Sep 30 '22 01:09

Michael Borgwardt