如何持久化像java.util.Currency这样的类?

时间:2015-04-14 05:44:21

标签: java hibernate persistence

我正在使用hibernate来保存我的数据。这是一个财务应用程序,我很难坚持应用程序中最基本的实体'Money'。我正在使用JodaMoney,但它是不可变的,所以我无法找到一个好的方法来坚持它。如果没有将资金存入数据库,那么就没有必要提出申请。当我甚至无法存储对象的状态时,我会对不变性做些什么呢? 然后我开始创建自己的'Money'(字段为BigDecimal amount和java.util.Currency for currency),我想使用java.util的'Currency'。但是,这没有公共构造函数,所以hibernate不能坚持这一点。 请指导我如何处理这个?

EDIT1:大多数基础类的代码:

@Entity
public class BasicMoney {

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

现在,当我创建此类的对象并尝试将其存储到数据库中时,它不起作用。 Hibernate抛出org.hibernate.InstantiationException:没有实体的默认构造函数:: java.util.Currency。所以,这是我面临的问题。

4 个答案:

答案 0 :(得分:4)

您可以使用解决方法

@Embedded
String currency;

public void setCurrency(Currency currency) {
    this.currency = currency.getCurrencyCode();
}

public Currency getCurrency() {
    return Currency.getInstance(currency);
}

答案 1 :(得分:3)

答案 2 :(得分:1)

而不是处理货币字符串和金额,而是教Hibernate关于你的类型。这样你会有:

private Money amount;

而不是

private BigDecimal amount;
private String currency;

因此您无需在所有地方进行转换。

我是这样做的:

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

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

3)创建这个简单的类:

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

就是这样。您将在整个过程中获得强大的输入。

答案 3 :(得分:0)

对不起,您回答的太晚了,但我没有将此选项作为答案,我认为这很优雅。您可以将JPA转换器与autoapply一起使用:

<all_urls>