如何在Hibernate中使用org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency类型映射Joda Money?

时间:2013-12-13 15:52:12

标签: java hibernate joda-money

试试这个:

@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency")
private org.joda.money.Money price;

获取此信息:

org.hibernate.MappingException: property mapping has wrong number of columns:domain.ClientOrderItem.price type: org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency


@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount",
parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "USD")})

效果很好,但我希望将货币存储在数据库中,并且能够使用不同的货币。

2 个答案:

答案 0 :(得分:4)

Jadira Usertype Unit Tests

有一个有效的例子
    @Entity
    @Table(name = "moneyAmountAndCurrency")
    @TypeDef(name = "testjoda_MoneyAmountWithCurrencyType", typeClass = PersistentMoneyAmountAndCurrency.class)
    public class MoneyAmountAndCurrencyHolder implements Serializable {

    private static final long serialVersionUID = -1674416082110551506L;

    @Columns(columns = { @Column(name = "MY_CURRENCY"), @Column(name = "MY_AMOUNT") })
    @Type(type = "testjoda_MoneyAmountWithCurrencyType")
    private Money money;

答案 1 :(得分:3)

简介

这实际上与Chris Pheby给出的答案没有什么不同。我只是在没有@TypeDef s等的情况下提供他的答案的版本,用于两个场景:

  1. 货币在MySQL中存储为CHAR(3),以便人们使用3-letter ISO-4217 code
  2. 提高数据的可读性
  3. 货币在MySQL中存储为SMALLINT,以便使用3-digit ISO-4217 number
  4. 略微提高效率

    在这两种情况下,Money字段的数量组件都存储为DECIMAL(9,2),大多数RDBMS需要5个字节的存储空间。当然,您可以使用任何其他确切的数据类型,以避免double / float附带的精确问题。

    场景1(3个字母的货币表示)

    我的虚构Payment @Entity对于方案(1)看起来像这样:

    package com.fictional;
    
    import org.hibernate.annotations.Columns;
    import org.hibernate.annotations.Type;
    import org.joda.money.CurrencyUnit;
    import org.joda.money.Money;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    
    /**
     * A fictional payment.
     */
    @Entity
    public class Payment {
    
        /**
         * Paid money.
         */
        @Columns(columns = {@Column(name = "paidMoneyCurrency"), @Column(name = "paidMoneyAmount")})
        @Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency")
        private Money paidMoney;
    
    
        /**
         * Sample construction of a money object belonging to a payment.
         */
        static public void testPayment()
        {
            Payment p = new Payment();
    
            p.paidMoney = Money.of(CurrencyUnit.EUR, 1234.56);
    
            // Hibernate persistence code to insert the new record
        }
    }
    

    静态方法只是在将此类对象提交到持久性存储之前实例化它的一个示例。

    数据库的相应DDL将是:

    CREATE TABLE Payment (
        paidMoneyCurrency CHAR(3) NOT NULL,
        paidMoneyAmount DECIMAL(9,2) NOT NULL
    );
    

    Hibernate生成的INSERT语句如下所示:

    INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES ('EUR', 1234.56);
    

    场景2(3位数货币表示)

    对于方案(2),您只需修改@Type字段的paidMoney注释即可阅读PersistentMoneyAmountAndCurrencyAsInteger而不是PersistentMoneyAmountAndCurrency(区别在于<类名称中的strong> AsInteger 后缀。

        // :
        // :
        @Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrencyAsInteger")
        private Money paidMoney;
        // :
        // :
    

    所有剩余的代码(甚至是静态方法中Money对象的实例化)都保持不变。

    然后你会得到以下DDL和Hibernate生成的相应INSERT语句(978是joda money为你自动计算的EUR的数字代码)

    CREATE TABLE Payment (
        paidMoneyCurrency SMALLINT NOT NULL,
        paidMoneyAmount DECIMAL(9,2) NOT NULL
    );
    
    INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES (978, 1234.56);