Project

General

Profile

Download (3.45 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.SessionImplementor;
13
import org.hibernate.type.BigDecimalType;
14
import org.hibernate.type.StandardBasicTypes;
15
import org.hibernate.usertype.UserType;
16

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

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

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

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

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

    
57
	@Override
58
	public boolean equals(Object arg0, Object arg1) throws HibernateException {
59
		return arg0.equals(arg1);
60
	}
61

    
62
	@Override
63
	public int hashCode(Object arg0) throws HibernateException {
64
		return arg0.hashCode();
65
	}
66

    
67
	@Override
68
	public boolean isMutable() {
69
		return false;
70
	}
71

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

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

    
93
	@Override
94
	public Object replace(Object arg0, Object arg1, Object arg2) throws HibernateException {
95
		return arg0;
96
	}
97

    
98
	@Override
99
	public Class<?> returnedClass() {
100
		return BigDecimal.class;
101
	}
102

    
103
	@Override
104
	public int[] sqlTypes() {
105
		return SQL_TYPES;
106
	}
107
}
(1-1/13)