Спящий режим и точность валюты - PullRequest
4 голосов
/ 30 декабря 2008

У меня спящий режим отображается следующим образом:

<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 на двойной, но это тоже не сработало. Проблема в том, что Hibernate действительно выполнил вставку правильно, и будущие операторы select работают для возврата текущего набора значений, но эта ошибка не позволяет мне продолжить обработку этого счета.

Поля bookFee, adminFee и totalFee должны быть валютами. Они определены в базе данных MySQL как десятичные (5,2).

Любая помощь в решении этой проблемы будет принята с благодарностью.

Ответы [ 5 ]

12 голосов
/ 30 декабря 2008

Использование float или double для денег абсолютно недопустимо и может даже быть незаконным (например, нарушение законов или, по крайней мере, правил). Это нужно исправить, тогда ошибка исчезнет. float имеет ограниченную точность и вообще не может точно представлять большинство десятичных дробей.

Для денег всегда ВСЕГДА используйте BigDecimal.

5 голосов
/ 30 декабря 2008

Я бы использовал целочисленный тип (int, long). Никогда не возникайте смешных проблем с ними, пока вы можете избежать переполнения.

1 голос
/ 30 декабря 2008

Вы пытались присвоить тип?

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

0 голосов
/ 30 декабря 2008

Было бы неплохо использовать собственное отображение Hibernate и определение класса.

0 голосов
/ 30 декабря 2008

В итоге я не использовал float, BigDecimal или double. Я вернулся к клиенту, и они согласились отбросить копейки, так как клиент всегда в любом случае взимал округленную сумму, поэтому нет необходимости хранить копейки. Однако мне все еще нужно выяснить, как правильно хранить валюты, так как это, скорее всего, произойдет снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...