Project

General

Profile

Download (3.59 KB) Statistics
| Branch: | Tag: | Revision:
1

    
2
package eu.etaxonomy.cdm.hibernate;
3

    
4
import java.io.Serializable;
5
import java.math.BigDecimal;
6
import java.sql.PreparedStatement;
7
import java.sql.ResultSet;
8
import java.sql.SQLException;
9
import java.sql.Types;
10

    
11
import org.hibernate.HibernateException;
12
import org.hibernate.engine.spi.SharedSessionContractImplementor;
13
import org.hibernate.type.BigDecimalType;
14
import org.hibernate.type.StandardBasicTypes;
15
import org.hibernate.usertype.UserType;
16

    
17
import eu.etaxonomy.cdm.common.CdmUtils;
18

    
19
/**
20
 * Hibernate {@link UserType} for BigDecimal with correct handling for scale.
21
 * Correct means that a BigDecimal with scale 2 will be stored and reloaded
22
 * with scale 2 even if the defined scale in the database has a higher scale defined.
23
 *
24
 * E.g. "1.32" is persisted as exactly this BigDecimal even if scale of the column is
25
 * defined with scale = 4. The default {@link BigDecimalType} stores and reloads it
26
 * as 1.3200 which is a difference when handling e.g. measurement values as it looses the
27
 * information about the exactness of the data.<BR><BR>
28
 *
29
 * Usage example with annotations (with type already declared in according package-info.java):<BR>
30
 *
31
 * <BR>@Columns(columns={@Column(name="xxx", precision = 18, scale = 9), @Column(name="xxx_scale")})
32
 * <BR>@Type(type="bigDecimalUserType")
33
 * <BR><BR>
34
 *
35
 * This class has been originally copied and adapted from
36
 * https://bitbucket.org/ratkins/bigdecimalusertype/src/default/<BR><BR>
37
 */
38
public class BigDecimalUserType implements UserType {
39

    
40
	private static final int[] SQL_TYPES = new int[] {
41
	        Types.NUMERIC, //for some reason Types.Decimal does not exist at least in MySQL Dialect
42
	        Types.INTEGER};
43

    
44
	@Override
45
	public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
46
		return deepCopy(arg0);
47
	}
48

    
49
	@Override
50
	public Object deepCopy(Object arg0) throws HibernateException {
51
		return arg0;
52
	}
53

    
54
	@Override
55
	public Serializable disassemble(Object arg0) throws HibernateException {
56
		return (Serializable) arg0;
57
	}
58

    
59
	@Override
60
	public boolean equals(Object arg0, Object arg1) throws HibernateException {
61
	    return CdmUtils.nullSafeEqual(arg0, arg1);
62
	}
63

    
64
	@Override
65
	public int hashCode(Object arg0) throws HibernateException {
66
	    assert (arg0 != null);
67
	    return arg0.hashCode();
68
	}
69

    
70
	@Override
71
	public boolean isMutable() {
72
		return false;
73
	}
74

    
75
	@Override
76
	public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {
77
		BigDecimal bigDecimal = (BigDecimal) StandardBasicTypes.BIG_DECIMAL.nullSafeGet(rs, names, session, owner);
78
		if (bigDecimal == null) {
79
			return null;
80
		}
81
		return bigDecimal.setScale(rs.getInt(names[1]), BigDecimal.ROUND_HALF_UP);
82
	}
83

    
84
	@Override
85
	public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
86
		if (value == null) {
87
			StandardBasicTypes.BIG_DECIMAL.nullSafeSet(st, null, index, session);
88
			StandardBasicTypes.INTEGER.nullSafeSet(st, null, index+1, session);
89
		} else {
90
			BigDecimal bdec = (BigDecimal)value;
91
			StandardBasicTypes.BIG_DECIMAL.nullSafeSet(st, bdec, index, session);
92
			StandardBasicTypes.INTEGER.nullSafeSet(st, bdec.scale(), index + 1, session);
93
		}
94
	}
95

    
96
	@Override
97
	public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
98
		return arg0;
99
	}
100

    
101
	@Override
102
	public Class<?> returnedClass() {
103
		return BigDecimal.class;
104
	}
105

    
106
	@Override
107
	public int[] sqlTypes() {
108
		return SQL_TYPES;
109
	}
110
}
(1-1/13)