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

6

尝试这样做:

@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个回答

5

这里有一个来自Jadira Usertype单元测试的工作示例:MoneyAmountAndCurrencyHolder.html

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

4

介绍

这与Chris Pheby的答案并没有什么不同。我提供的是他的答案版本,没有@TypeDef等内容,适用于以下两种情况:

  1. 货币以MySQL中的CHAR(3)存储,以便人类更好读取数据,使用3个字母的ISO-4217代码
  2. 货币以MySQL中的SMALLINT存储,以稍微提高效率,使用3位数字的ISO-4217编号
在这两种情况下,“Money”字段的“amount”部分都被存储为“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),您只需修改paidMoney字段的@Type注释为PersistentMoneyAmountAndCurrencyAsInteger而不是PersistentMoneyAmountAndCurrency(类名中的区别在于AsInteger后缀)。

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

所有剩余的代码(甚至是静态方法中Money对象的实例化)保持不变。
然后,Hibernate将生成以下DDL和相应的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);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接