如何像java.util.Currency一样坚持类?

How to persist classes like java.util.Currency?

我正在使用休眠来保存我的数据。这是一个财务应用程序,我很难坚持应用程序的最基本实体 'Money'。我使用的是 JodaMoney,但它是不可变的,所以我无法找到一种好的方法来保留它。如果不将我的钱存入数据库,就没有必要制作应用程序。当我什至无法存储我的对象的状态时,我将如何处理不可变性? 然后我开始创建自己的 'Money'(字段为 BigDecimal 金额和 java.util.Currency 货币),我想使用 'Currency' 的 java.util 。但是,它没有 public 构造函数,因此 hibernate 无法保留它。 请指导我如何处理这个问题?

EDIT1:最基本的代码class:

@Entity
public class BasicMoney {

    @Embedded
    @Id
    private BigDecimal amount;
    @Embedded
    private Currency currency;
    //getters and setters, other methods
}

现在,当我创建这个 class 的对象并尝试将其存储到数据库中时,它不起作用。休眠抛出:

org.hibernate.InstantiationException: No default constructor for entity: : java.util.Currency

所以,这就是我面临的问题。

您可以使用解决方法

@Embedded
String currency; //store data as a string

public void setCurrency(Currency currency) {
    this.currency = currency.getCurrencyCode(); //conversion to an actual currency
}

public Currency getCurrency() {
    return Currency.getInstance(currency); //conversion to an actual currency
}

与其处理货币字符串和金额,不如教 Hibernate 您的类型。这样你就会:

private Money amount;

而不是

private BigDecimal amount;
private String currency;

所以你不需要到处转换。

这是我的做法:

1) 不用JodaMoney,使用JavaMoney,预计会包含在Java中的JSR-354项目 9.如果你想坚持使用JodaMoney,你不需要下面的第 3 步。

2) 将此 UserType library 添加到您的 class 路径

3) 创建这个简单的 class:

   public class CustomPersistentMoneyAmountAndCurrency extends AbstractMultiColumnUserType<MonetaryAmount> {  

    private static final ColumnMapper<?, ?>[] COLUMN_MAPPERS = new ColumnMapper<?, ?>[] { new CustomStringColumnCurrencyUnitMapper(), new BigDecimalBigDecimalColumnMapper() };

    private static final String[] PROPERTY_NAMES = new String[]{ "currency", "number" };

    @Override
    protected ColumnMapper<?, ?>[] getColumnMappers() {
        return COLUMN_MAPPERS;
    }

    @Override
    protected Money fromConvertedColumns(Object[] convertedColumns) {

        CurrencyUnit currencyUnitPart = (CurrencyUnit) convertedColumns[0];
        BigDecimal amountPart = (BigDecimal) convertedColumns[1];
        return Money.of(amountPart, currencyUnitPart);
    }

    @Override
    protected Object[] toConvertedColumns(MonetaryAmount value) {

        return new Object[] { value.getCurrency(), value.getNumber().numberValue(BigDecimal.class) };
    }

    @Override
    public String[] getPropertyNames() {
        return PROPERTY_NAMES;
    }
}

4) 现在无论你想在你的实体中使用它,你都可以这样做:

   @TypeDefs(value = {
        @TypeDef(name = "moneyAmountWithCurrencyType", typeClass =        CustomPersistentMoneyAmountAndCurrency.class)
})
@Entity
@Table(name = "account_entry")
public class AccountEntry {

    private Money referenceMoney;
    ...
    @Basic( optional = false )
    @Columns(columns = {
            @Column( name = "reference_money_currency", nullable = false, length = 3  ),
            @Column( name = "reference_money", nullable = false  )
    })
    @Type(type = "moneyAmountWithCurrencyType")
    public Money getReferenceMoney() {
        return this.referenceMoney;
    }
  }

就是这样。您将始终获得强大的打字能力。

Hibernate 本身支持 java.util.Currency。 https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/types.html#types-basic-value-currency

抱歉回答晚了,但我没有将此选项视为答案,而且我认为它非常优雅。您可以使用具有自动应用功能的 JPA 转换器:

@Converter(autoApply = true)
public class CurrencyConverter implements AttributeConverter<Currency, String> {

    @Override
    public String convertToDatabaseColumn(Currency currency) {
        return currency.getCurrencyCode();
    }

    @Override
    public Currency convertToEntityAttribute(String currencyCode) {
        return Currency.getInstance(currencyCode);
    }
}