2011-11-27 39 views

回答

5

好吧,我把你的意见,并炮制了钱的自定义类型为乔达库中的定义,作为参考的人可以看看它here,这里使用和测试自定义类型here

+0

我认为你的实现在'setPropertyValue()'中有一个错误 - Money对象是不可变的,并且'money.withAmount((BigDecimal)value);'只是创建一个新对象 –

+0

Point采取了变化:),我不知道何时基于我的分析hibernate调用setPropertyValue()方法时,只有nullSafeSet方法似乎被hibernate调用。 – Sudarshan

+0

嗯......你是否知道你仍然只是在改变局部变量?我认为为不可变对象实现此方法的唯一正确方法是引发UnsupportedOperationException。幸运的是,正如你所说,它似乎并没有被调用。 –

1

Joda-Money非常新颖,所以没有人为它提供Hibernate映射也就不足为奇了。

但是,编写自定义Hibernate类型适配器非常简单。如果您查看JodaTime适配器的源代码,您会发现它们非常简单。请参阅docs了解如何编写自己的。

+0

你知道哪些钱库与hibernate兼容吗?在适配器方面 – Sudarshan

+3

好吧,我接受了您的建议,并为Joda库中定义的Money制作了一个自定义类型,作为参考,人们可以查看它[在此](http://code.google.com/p/ddd) -cqrs-base-project/source/browse/trunk/src/main/java/org/nthdimenzion/ddd/domain/sharedkernel/MoneyType.java),用法[here](http://code.google.com/p /ddd-cqrs-base-project/source/browse/trunk/src/main/java/com/librarymanagement/domain/Book.java)并测试自定义类型[here](http://code.google.com /p/ddd-cqrs-base-project/source/browse/trunk/src/test/java/integration/com/librarymanagement/BookTest.java) – Sudarshan

+1

Sudarshan的评论应该提升为答案(如果可以的话)IMO 。 – Rich

4

User Type项目从版本3.0.0开始支持joda-money 0.6。但请注意,这需要Hibernate 4。此外目前的joda-money版本是0.8

如果你想在Hibernate 3中使用它,请使用Sudarshan anwser中的示例(在编写本文时已对其进行了修改)。

+0

我认为这是现在最好的答案。 – LaurentG

5

由于在Sudarshan的答案中的示例链接被破坏,下面是org.joda.money.BigMoney的一个简单的自定义用户类型的实现,它将货币对象保存为两列金额和货币)以及如何使用它的示例。它适用于org.joda.money.Money

package test; 

import java.io.Serializable; 
import java.math.BigDecimal; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.util.Currency; 

import org.apache.commons.lang.ObjectUtils; 
import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.type.StandardBasicTypes; 
import org.hibernate.type.Type; 
import org.hibernate.usertype.CompositeUserType; 
import org.joda.money.BigMoney; 
import org.joda.money.CurrencyUnit; 

public class MoneyUserType implements CompositeUserType 
{ 
    private static final String[] PROPERTY_NAMES = {"amount", "currencyUnit"}; 
    private static final Type[] PROPERTY_TYPES = {StandardBasicTypes.BIG_DECIMAL, StandardBasicTypes.CURRENCY}; 

    public MoneyUserType() 
    { 
     super(); 
    } 

    public Object assemble(final Serializable cached, final SessionImplementor session, final Object owner) 
    throws HibernateException 
    { 
     return cached; 
    } 

    public Serializable disassemble(final Object value, final SessionImplementor session) throws HibernateException 
    { 
     return (Serializable) value; 
    } 

    public String[] getPropertyNames() 
    { 
     return PROPERTY_NAMES.clone(); 
    } 

    public Type[] getPropertyTypes() 
    { 
     return PROPERTY_TYPES.clone(); 
    } 

    public Object getPropertyValue(final Object component, final int property) throws HibernateException 
    { 
     BigMoney money = (BigMoney) component; 
     return (property == 0) ? money.getAmount() : money.getCurrencyUnit().toCurrency(); 
    } 

    public Object nullSafeGet(final ResultSet rs, final String[] names, final SessionImplementor session, 
    final Object owner) throws HibernateException, SQLException 
    { 
     BigDecimal amount = StandardBasicTypes.BIG_DECIMAL.nullSafeGet(rs, names[0], session); 
     Currency currency = StandardBasicTypes.CURRENCY.nullSafeGet(rs, names[1], session); 
     return BigMoney.of(CurrencyUnit.of(currency), amount); 
    } 

    public void nullSafeSet(final PreparedStatement st, final Object value, final int index, 
    final SessionImplementor session) throws HibernateException, SQLException 
    { 
     BigMoney money = (BigMoney) value; 
     BigDecimal amount = (money == null) ? null : money.getAmount(); 
     Currency currency = (money == null) ? null : money.getCurrencyUnit().toCurrency(); 

     StandardBasicTypes.BIG_DECIMAL.nullSafeSet(st, amount, index, session); 
     StandardBasicTypes.CURRENCY.nullSafeSet(st, currency, index + 1, session); 
    } 

    public Object replace(final Object original, final Object target, final SessionImplementor session, 
    final Object owner) throws HibernateException 
    { 
     return deepCopy(original); 
    } 

    public void setPropertyValue(final Object component, final int property, final Object value) 
    throws HibernateException 
    { 
     throw new HibernateException("Money is immutable."); 
    } 

    public Object deepCopy(final Object value) throws HibernateException 
    { 
     return (value != null) ? BigMoney.of(((BigMoney) value).getCurrencyUnit(), 
     ((BigMoney) value).getAmount()) : null; 
    } 

    public boolean equals(final Object x, final Object y) throws HibernateException 
    { 
     return ObjectUtils.equals(x, y); 
    } 

    public int hashCode(final Object x) throws HibernateException 
    { 
     return ObjectUtils.hashCode(x); 
    } 

    public boolean isMutable() 
    { 
     return false; 
    } 

    public Class<?> returnedClass() 
    { 
     return BigMoney.class; 
    } 
} 

用法:

@Type(type = "test.MoneyUserType") 
@Columns(columns = {@Column(name = "AMOUNT"), @Column(name = "CURRENCY")}) 
private BigMoney money; 
4

Based on http://jadira.sourceforge.net

货币类型通常由一个货币和金额。 Jadira可以仅使用参数配置货币来存储数据库的金额。例如:

@Column 
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount", 
    parameters = {@org.hibernate.annotations.Parameter(name = "currencyCode", value = "USD")}) 
private Money money; 

Alternatively, with other types two columns to hold the amount an currency: 

@Columns(columns = { @Column(name = "MY_CURRENCY"), @Column(name = "MY_AMOUNT") }) 
@Type(type = "org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmountAndCurrency") 
private Money money; 
+0

感谢你;) – micdcar