lunes, 24 de febrero de 2014

Creando un UserType de hibernate que se aplique a todas las entidades.

Hibernate posee un mecanismo muy potente para controlar la manera en que ocurre la conversion de valores obtenidos de la fuente de datos a valores Java. Se trata de los UserTypes. Por ejemplo, si utilizas una Base de Datos muy antigua que mantiene siempre al final de cada cadena espacios en blanco hasta rellenar la longitud de la columna, mediante un UserType puedes redefinir la manera en que la cadena es leida de la base de datos y escrita en el String de destino de Java. Para manipular dicho proceso basta con implementar una clase heredera que redefina algunos métodos y dejar que el framework realice el resto

package es.hib.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;

public class TrimmedString implements UserType {

public TrimmedString() {
super();
}

@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}

@Override
public Class returnedClass() {
return String.class;
}

@Override
public boolean equals(Object x, Object y) throws HibernateException {
return (x == y) || (x != null && y != null && (x.equals(y)));
}

@Override
public Object deepCopy(Object value) throws HibernateException {
if (value == null)
return null;
return new String((String) value);
}

@Override
public boolean isMutable() {
return false;
}

@Override
public Object assemble(Serializable cached, Object owner) throws

 HibernateException {
return cached;
}

@Override
public Serializable disassemble(Object obje) throws 

HibernateException {
return (Serializable) obje;
}

@Override
public int hashCode(Object obje) throws HibernateException {
return obje.hashCode();
}

@Override
public Object nullSafeGet(ResultSet rs, String[] names, 

SessionImplementor arg2, Object owner) throws HibernateException,
SQLException {

String val = rs.getString(names[0]);

if (null == val) {

return (null);
}
return val.trim();
}

@Override
public void nullSafeSet(PreparedStatement st, Object value, 

int index, SessionImplementor arg3) throws HibernateException,
SQLException {
st.setString(index, (String) value);
}

@Override
public Object replace(Object original, Object target, Object owner) 

throws HibernateException {

return original;
}
}

Ya teniendo el UserType implementado puede decidirse si usarse localmente

@Type(type="es.hib.usertype.TrimmedString")
@Column(name = "DESCRIPCION")
private String descripcion;

o globalmente, o sea, aplicarlo a la conversion de todos los VARCHAR en String de la aplicación. Para esto se debe crear en el paquete que contiene las entidades el siguiente archivo package-info.java. El mismo es una anotación a nivel de paquetes que surtirá el mismo efecto que si se anotaran una a una todas las clases del paquete dado.

@org.hibernate.annotations.TypeDef(name = "trimmedString", 
defaultForType = String.class, typeClass = TrimmedString.class)
package es.hib.entities;

import es.hib.usertype.TrimmedString;

Después de creado el package-info.java, ya solo se necesita que hibernate lo note. Para esto debe de agregarse,  programaticamente cuando se esten cargando las configuraciones añadir la siguiente sentencia.

configuration.addPackage("es.hib.entities")


No hay comentarios:

Publicar un comentario