Joda-Money通过hibernate持久化

时间:2011-11-27 19:13:11

标签: java hibernate joda-money

JodaTime有一个provides Hibernate persistence的库。最近我开始查看Joda-Money,并开始看看如何使用hibernate持久保存,我没有看到任何库。

有什么建议吗?

6 个答案:

答案 0 :(得分:6)

由于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;

答案 1 :(得分:4)

User Type项目包括Joda Money支持。

答案 2 :(得分:4)

好的,我接受了你的建议并为Joda图书馆中定义的Money创建了一个自定义类型,作为参考,人们可以查找here,此处使用并测试自定义类型here

答案 3 :(得分:4)

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

如果你想在Hibernate 3中使用它,请使用Sudarshan anwser中的示例(在撰写本文时它已被窃听)。

答案 4 :(得分: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;

答案 5 :(得分:1)

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

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