介绍
这实际上与Chris Pheby给出的答案没有什么不同。我只是@TypeDef
为两个场景提供了一个没有 s 等的答案版本:
- 在 MySQL 中存储为 a的货币
CHAR(3)
,以便人类使用3字母ISO-4217 代码更好地读取数据
- 使用3位ISO-4217 数字在 MySQL 中存储为 a的货币
SMALLINT
以略微提高效率
在这两种情况下,字段的数量组件Money
都存储为 a DECIMAL(9,2)
,对于大多数 RDBMS 来说,这需要 5 个字节的存储空间。当然,您可以使用任何其他精确的数据类型,以避免double
/可能出现的精度问题float
。
场景 1(3 个字母的货币表示)
对于场景(1),我的虚构Payment
@Entity
看起来像这样:
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;
/**
* A fictional payment.
*/
@Entity
public class Payment {
/**
* Paid money.
*/
@Columns(columns = {@Column(name = "paidMoneyCurrency"), @Column(name = "paidMoneyAmount")})
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency")
private Money paidMoney;
/**
* Sample construction of a money object belonging to a payment.
*/
static public void testPayment()
{
Payment p = new Payment();
p.paidMoney = Money.of(CurrencyUnit.EUR, 1234.56);
// Hibernate persistence code to insert the new record
}
}
静态方法只是在将此类对象提交到持久存储之前对其进行实例化的示例。
数据库对应的 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(3 位货币表示)
对于场景(2),您只需将字段的@Type
注释修改paidMoney
为读取PersistentMoneyAmountAndCurrencyAsInteger
而不是PersistentMoneyAmountAndCurrency
(不同之处在于类名中的AsInteger后缀)。
// :
// :
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrencyAsInteger")
private Money paidMoney;
// :
// :
所有剩余的代码(甚至Money
是静态方法中的对象实例化)都保持不变。
然后你会得到下面的DDL和INSERT
Hibernate生成的相应语句(是joda money为你自动计算978
的数字代码)EUR
CREATE TABLE Payment (
paidMoneyCurrency SMALLINT NOT NULL,
paidMoneyAmount DECIMAL(9,2) NOT NULL
);
INSERT INTO Payment (paidMoneyCurrency, paidMoneyAmount) VALUES (978, 1234.56);