我正在使用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。所以,这是我面临的问题。
答案 0 :(得分:4)
您可以使用解决方法
@Embedded
String currency;
public void setCurrency(Currency currency) {
this.currency = currency.getCurrencyCode();
}
public Currency getCurrency() {
return Currency.getInstance(currency);
}
答案 1 :(得分:3)
Hibernate本身就支持java.util.Currency。 https://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/types.html#types-basic-value-currency
答案 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>