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")})

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

4

2 回答 2

5

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;
于 2013-12-14T00:01:44.107 回答
4

介绍

这实际上与Chris Pheby给出的答案没有什么不同。我只是@TypeDef为两个场景提供了一个没有 s 等的答案版本:

  1. 在 MySQL 中存储为 a的货币CHAR(3),以便人类使用3字母ISO-4217 代码更好地读取数据
  2. 使用3ISO-4217 数字在 MySQL 中存储为 a的货币SMALLINT以略微提高效率

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

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

对于场景(1),我的虚构Payment @Entity看起来像这样:

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(不同之处在于类名中的AsInteger后缀)。

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

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

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

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

INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES (978, 1234.56);
于 2015-09-12T16:58:42.207 回答