forked from vladmihalcea/hypersistence-utils
/
MonetaryAmountType.java
133 lines (108 loc) · 4.26 KB
/
MonetaryAmountType.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.vladmihalcea.hibernate.type.money;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.hibernate.usertype.CompositeUserType;
import org.javamoney.moneta.Money;
import javax.money.MonetaryAmount;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;
import static java.sql.Types.DECIMAL;
import static java.sql.Types.VARCHAR;
/**
* Maps a {@link MonetaryAmount} object type onto two columns (amount and currency).
*
* <p>
* For more details about how to use it,
* check out <a href="https://vladmihalcea.com/monetaryamount-jpa-hibernate/">this article</a>
* on <a href="https://vladmihalcea.com/">vladmihalcea.com</a>.
*
* @author Piotr Olaszewski
*/
public class MonetaryAmountType implements CompositeUserType {
@Override
public String[] getPropertyNames() {
return new String[]{"amount", "currency"};
}
@Override
public Type[] getPropertyTypes() {
return new Type[]{BigDecimalType.INSTANCE, StringType.INSTANCE};
}
@Override
public Object getPropertyValue(Object component, int property) throws HibernateException {
MonetaryAmount monetaryAmount = (MonetaryAmount) component;
if (property == 0) {
return monetaryAmount.getNumber().numberValue(BigDecimal.class);
} else if (property == 1) {
return monetaryAmount.getCurrency();
}
throw new IllegalArgumentException("Invalid property index " + property + " for class " + component.getClass());
}
@Override
public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
throw new HibernateException("Call setPropertyValue on immutable type " + component.getClass());
}
@Override
public Class returnedClass() {
return MonetaryAmount.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
String amountColumnName = names[0];
String currencyColumnName = names[1];
BigDecimal amount = rs.getBigDecimal(amountColumnName);
if(amount == null) {
return null;
}
String currency = rs.getString(currencyColumnName);
return Money.of(amount, currency);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int amountColumnIndex, SharedSessionContractImplementor session) throws HibernateException, SQLException {
int currencyColumnIndex = amountColumnIndex + 1;
if (value == null) {
st.setNull(amountColumnIndex, DECIMAL);
st.setNull(currencyColumnIndex, VARCHAR);
} else {
MonetaryAmount monetaryAmount = (MonetaryAmount) value;
BigDecimal amount = monetaryAmount.getNumber().numberValue(BigDecimal.class);
String currency = monetaryAmount.getCurrency().getCurrencyCode();
st.setBigDecimal(amountColumnIndex, amount);
st.setString(currencyColumnIndex, currency);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value, SharedSessionContractImplementor session) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner) throws HibernateException {
return original;
}
}