如何持久化java.util.Currency之类的类?

Anm*_*pta 5 java persistence hibernate

我正在使用休眠来保留我的数据。这是一个财务应用程序,我很难保留该应用程序的最基本实体“金钱”。我使用的是JodaMoney,但它是不可变的,因此无法找到持久的方法。而且,如果没有将我的钱花在数据库上,就没有必要编写该应用程序。当我什至无法存储对象状态时,如何处理不变性?然后,我开始创建自己的'Money'(字段为BigDecimal量,而java.util.Currency为货币字段),我想使用java.util的'Currency'。但是,由于没有公共构造函数,因此休眠不能持久化。请指导我如何处理?

EDIT1:最基本的类的代码:

@Entity
public class BasicMoney {

    @Embedded
    @Id
    private BigDecimal amount;
    @Embedded
    private Currency currency;
    //getters and setters, other methods
}
Run Code Online (Sandbox Code Playgroud)

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

Evg*_*eev 6

您可以使用解决方法

@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
}
Run Code Online (Sandbox Code Playgroud)

  • 尝试 System.out.println(Currency.getInstance("USD") ==Currency.getInstance("USD")); 它返回 true (2认同)

wwa*_*dge 5

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

private Money amount;
Run Code Online (Sandbox Code Playgroud)

代替

private BigDecimal amount;
private String currency;
Run Code Online (Sandbox Code Playgroud)

所以你不需要到处转换。

这是我的方法:

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

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
  }
Run Code Online (Sandbox Code Playgroud)

就是这样。您将在整个过程中获得强大的打字能力。