Question

There is a library for JodaTime that provides Hibernate persistence. Recently I started looking at Joda-Money and started to see how that can be persisted using hibernate and I do not see any library.

Any suggestions?

Was it helpful?

Solution 4

Okay I took your advice and cooked up a custom type for Money as defined in the Joda Library, as a reference people can look it up here,usage here and test for the custom type here

OTHER TIPS

Since the link to the example in Sudarshan's answer is broken, here is an implementation of a simple custom user type for org.joda.money.BigMoney, that persists money objects in two columns amount and currency) and an example of how to use it. It works the same for 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;
    }
}

Usage:

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

The User Type project includes Joda Money support.

The User Type project provides support for joda-money 0.6 since version 3.0.0. Please note however that this requires Hibernate 4. Also the current joda-money version is 0.8

If you want to use it with Hibernate 3 use the example in Sudarshan anwser (it's bugged at the time of writing).

Based on http://jadira.sourceforge.net

Money Types typically consist of a currency and amount. Jadira makes it possible to store only the amount to the database with the currency configured using a parameter. For example:

@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;

Joda-Money's very new, so it's no surprise that noone's provided a Hibernate mapping for it yet.

However, writing custom Hibernate type adapters is pretty straightforward. If you look at the source for the JodaTime adapters, you'll see they're really simple. See the docs for how to write your own.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top