DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world
Hibernate UserTypeSupport
A base class for Hibernate UserTypes, that handles absolutely everything except the conversion between JDBC value and mapped entity value.
package net.andrewspencer.util.hibernate;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
/**
* <p>
* Base class for Hibernate UserTypes.
* </p>
* <p>
* This class handles all the mechanics except for the conversion itself
* between JDBC and entity values, for which you provide an instance of JdbcEntityConverter.
*
* @author Andrew Spencer
*/
public class UserTypeSupport<MappedClass, JdbcClass> implements UserType {
/**
* Conversion strategy between the value seen by JDBC and the representation
* used in the entity class.
*
* @param <MappedClass>
* The class of the property as declared in the entity
* @param <JdbcClass>
* The class of the value returned by or passed to JDBC
* (JDBC must be able to convert between this class and
* the SQL type; the JDBC specs list the available conversions).
* @author spencera
*/
public interface JdbcEntityConverter<MappedClass, JdbcClass> {
/**
* Converts the JDBC value to the value mapped and exposed by the entity
*
* @param value
* the value returned by JDBC (guaranteed non null)
* @return the value to be set in the entity
* @throws SQLException
*/
MappedClass jdbcToEntity(JdbcClass databaseValue) throws SQLException;
/**
* @param objectValue
* the value present in the entity (guaranteed non null)
* @return the value to pass to JDBC
*/
Object entityToJdbc(MappedClass objectValue);
}
private Class<MappedClass> mappedClass = null;
private Class<JdbcClass> jdbcClass = null;
private int sqlType;
private String dbTypeName = null;
private JdbcEntityConverter<MappedClass, JdbcClass> jdbcEntityConverter;
/**
* @param mappedClass
* The class of the property defined on the entity
* @param jdbcClass
* The class of the value passed to or returned from JDBC
* @param sqlType
* The SQL type: one of the constants defined by java.sql.Types
* @param jdbcEntityConverter
* The conversion strategy
*/
protected UserTypeSupport(final Class<MappedClass> mappedClass, final Class<JdbcClass> jdbcClass,
final int sqlType, final JdbcEntityConverter<MappedClass, JdbcClass> databaseRepresentation) {
this.mappedClass = mappedClass;
this.jdbcClass = jdbcClass;
this.sqlType = sqlType;
this.jdbcEntityConverter = databaseRepresentation;
}
public int[] sqlTypes() {
return new int[] {sqlType};
}
public Class<MappedClass> returnedClass() {
return mappedClass;
}
public Object nullSafeGet(final ResultSet resultSet, final String[] names, final Object owner)
throws HibernateException, SQLException {
if (resultSet.wasNull()) {
return null;
}
String columnName = names[0];
int columnIndex = resultSet.findColumn(columnName);
@SuppressWarnings("unchecked")
// This overloading of getObject() ensures returned value is of correct type
JdbcClass dbValue =
(JdbcClass) resultSet.getObject(columnIndex, mapDbTypeNameToJdbcType(resultSet, columnIndex));
// exception on preceding line? Ensure native SQL type is indeed convertible into <JdbcClass>
return jdbcEntityConverter.jdbcToEntity(dbValue);
}
private Map<String, Class<?>> mapDbTypeNameToJdbcType(final ResultSet resultSet, int columnIndex)
throws SQLException {
Map<String, Class<?>> dbTypeNameToJdbcType = new HashMap<String, Class<?>>();
// map only for the type we are interested in returning
dbTypeNameToJdbcType.put(retrieveColumnTypeName(resultSet, columnIndex), jdbcClass);
return dbTypeNameToJdbcType;
}
private synchronized String retrieveColumnTypeName(final ResultSet resultSet, final int columnIndex) throws SQLException {
if (dbTypeName == null) {
dbTypeName = resultSet.getMetaData().getColumnTypeName(columnIndex);
}
return dbTypeName;
}
public void nullSafeSet(final PreparedStatement preparedStatement, final Object value, final int index)
throws HibernateException, SQLException {
if (null == value) {
preparedStatement.setNull(index, sqlType);
} else {
@SuppressWarnings("unchecked") // type must be <MappedClass> if Hibernate mapping is correct
MappedClass valueCast = (MappedClass) value;
preparedStatement.setObject(index, jdbcEntityConverter.entityToJdbc(valueCast), sqlType);
}
}
public Object deepCopy(final Object value) throws HibernateException {
return value;
}
public boolean isMutable() {
return false;
}
public Object assemble(final Serializable cached, final Object owner) throws HibernateException {
return cached;
}
public Serializable disassemble(final Object value) throws HibernateException {
return (Serializable) value;
}
public Object replace(final Object original, final Object target, final Object owner)
throws HibernateException {
return original;
}
public int hashCode(final Object x) throws HibernateException {
return x.hashCode();
}
public boolean equals(final Object x, final Object y) throws HibernateException {
if (x == y) {
return true;
}
if (null == x || null == y) {
return false;
}
return x.equals(y);
}
}






