介绍
这与Chris Pheby的答案并没有什么不同。我提供的是他的答案版本,没有@TypeDef
等内容,适用于以下两种情况:
- 货币以MySQL中的
CHAR(3)
存储,以便人类更好读取数据,使用3个字母的ISO-4217代码
- 货币以MySQL中的
SMALLINT
存储,以稍微提高效率,使用3位数字的ISO-4217编号
在这两种情况下,“Money”字段的“amount”部分都被存储为“DECIMAL(9,2)”,在大多数RDBMS中需要5个字节的存储空间。当然,您可以使用任何其他精确数据类型来避免使用“double”/“float”可能出现的精度问题。
场景1(3个字母的货币表示法):
我的虚构“Payment”@Entity在此场景(1)中如下所示:
package com.fictional;
import org.hibernate.annotations.Columns;
import org.hibernate.annotations.Type;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;
import javax.persistence.Column;
import javax.persistence.Entity;
@Entity
public class Payment {
@Columns(columns = {@Column(name = "paidMoneyCurrency"), @Column(name = "paidMoneyAmount")})
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency")
private Money paidMoney;
static public void testPayment()
{
Payment p = new Payment();
p.paidMoney = Money.of(CurrencyUnit.EUR, 1234.56);
}
}
这个静态方法只是实例化这样一个对象的示例,然后将其提交到持久性存储中。
相应的数据库DDL如下:
CREATE TABLE Payment (
paidMoneyCurrency CHAR(3) NOT NULL,
paidMoneyAmount DECIMAL(9,2) NOT NULL
);
Hibernate生成的
INSERT
语句如下:
INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES ('EUR', 1234.56);
方案二(三位货币表示法)
对于方案(2),您只需修改paidMoney
字段的@Type
注释为PersistentMoneyAmountAndCurrencyAsInteger
而不是PersistentMoneyAmountAndCurrency
(类名中的区别在于AsInteger后缀)。
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrencyAsInteger")
private Money paidMoney;
所有剩余的代码(甚至是静态方法中
Money
对象的实例化)保持不变。
然后,Hibernate将生成以下DDL和相应的
INSERT
语句(
978
是由joda money自动计算为
EUR
的数字代码)。
CREATE TABLE Payment (
paidMoneyCurrency SMALLINT NOT NULL,
paidMoneyAmount DECIMAL(9,2) NOT NULL
);
INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES (978, 1234.56);