如何像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);
}
}
我正在使用休眠来保存我的数据。这是一个财务应用程序,我很难坚持应用程序的最基本实体 '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);
}
}