miércoles, 11 de enero de 2012

Crear tipo enumerado para hibernate

Para crear el tipo enumerado en primer lugar he necesitado la clase que viene públicada en el enlace http://appfuse.org/display/APF/Java+5+Enums+Persistence+with+Hibernate y que añado a continuación.

package com.manager.types;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.HibernateException;
import org.hibernate.type.NullableType;
import org.hibernate.type.TypeFactory;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import org.jboss.logging.Logger;


public class GenericEnumUserType implements UserType, ParameterizedType {
    private static final Logger log = Logger.getLogger(GenericEnumUserType.class);
   
    private static final String DEFAULT_IDENTIFIER_METHOD_NAME = "name";
    private static final String DEFAULT_VALUE_OF_METHOD_NAME = "valueOf";

    private Class<? extends Enum> enumClass;
    private Class<?> identifierType;
    private Method identifierMethod;
    private Method valueOfMethod;
    private NullableType type;
    private int[] sqlTypes;

    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enumClass");
        try {                 
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException cfne) {
            throw new HibernateException("Enum class not found", cfne);
        }

        String identifierMethodName = parameters.getProperty("identifierMethod", DEFAULT_IDENTIFIER_METHOD_NAME);

        try {
            identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
            identifierType = identifierMethod.getReturnType();
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain identifier method", e);
        }

        type = (NullableType) TypeFactory.basic(identifierType.getName());

        if (type == null)
            throw new HibernateException("Unsupported identifier type " + identifierType.getName());

        sqlTypes = new int[] { type.sqlType() };

        String valueOfMethodName = parameters.getProperty("valueOfMethod", DEFAULT_VALUE_OF_METHOD_NAME);

        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[] { identifierType });
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain valueOf method", e);
        }
    }

    public Class returnedClass() {
        return enumClass;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { 
        Object identifier = type.get(rs, names[0]);
        if (rs.wasNull()) {
            return null;
        }
       
        try {
            return valueOfMethod.invoke(enumClass, new Object[] { identifier });
        } catch (Exception e) {
            throw new HibernateException("Exception while invoking valueOf method '" + valueOfMethod.getName() + "' of " +
                    "enumeration class '" + enumClass + "'", e);
        }
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        try {
            if (value == null) {
                st.setNull(index, type.sqlType());
            } else {
                Object identifier = identifierMethod.invoke(value, new Object[0]);
                type.set(st, identifier, index);
            }
        } catch (Exception e) {
            throw new HibernateException("Exception while invoking identifierMethod '" + identifierMethod.getName() + "' of " +
                    "enumeration class '" + enumClass + "'", e);
        }
    }

    public int[] sqlTypes() {
        return sqlTypes;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public boolean isMutable() {
        return false;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

Después he creado la clase enumerada "NewsState" que quería que se mapeara con su correspondiente tipo en la base de datos. Esta clase la he tenido que crear en su propio fichero .java sino no me funcionaba.

package com.manager.types;

public enum NewsState {
    RELEASED,
    NO_RELEASED,
    DELETE
}

Una vez creado los tipos, he utilizado el anterior en la clase "News".


package com.manager.entities;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import com.manager.types.NewsState;

public class News implements Serializable{
   
    /**
     *
     */
    private static final long serialVersionUID = 2102522851404135715L;
    private String newsId;
    private NewsState newsState;
    private Calendar dateCreate;
    private Calendar dateUpdate;
    private Calendar dateDelete;
   
    public News(String newsId) {
        this(newsId, NewsState.RELEASED);
    }
   
    public News(String newsId, NewsState newsState) {
        this(newsId, newsState, Calendar.getInstance(), Calendar.getInstance(), Calendar.getInstance());
    }
       
    public News(String newsId, NewsState newsState, Calendar dateCreate,
            Calendar dateUpdate, Calendar dateDelete) {       
        this.newsId = newsId;
        this.newsState = newsState;
        this.dateCreate = dateCreate;
        this.dateUpdate = dateUpdate;
        this.dateDelete = dateDelete;
    }

    public String getNewsId() {
        return newsId;
    }
    public void setNewsId(String newsId) {
        this.newsId = newsId;
    }
    public NewsState getNewsState() {
        return newsState;
    }
    public void setNewsState(NewsState newsState) {
        this.newsState = newsState;
    }
    public Date getDateCreate() {
        return dateCreate.getTime();
    }
    public void setDateCreate(Date dateCreate) {
        this.dateCreate.setTime(dateCreate);
    }
    public Date getDateUpdate() {
        return dateUpdate.getTime();
    }
    public void setDateUpdate(Date dateUpdate) {
        this.dateUpdate.setTime(dateUpdate);
    }
    public Date getDateDelete() {
        return dateDelete.getTime();
    }
    public void setDateDelete(Date dateDelete) {
        this.dateDelete.setTime(dateDelete);
    }   
}

 Y lo he asociado todo en el fichero news.hbm.xml.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">


<hibernate-mapping package="com.manager.entities">
    <class name="News" table="news" schema="manager">
        <id name="newsId" column="news_id" type="string" length="15" unsaved-value="null">
            <generator class="assigned" />
        </id>
        <property name="newsState" column="news_state" not-null="true">
            <type name="com.manager.types.GenericEnumUserType">
                  <param name="enumClass">com.manager.types.NewsState</param>
            </type>             
          </property>              
        <property name="dateCreate" column="news_date_create" type="timestamp"/>
        <property name="dateUpdate" column="news_date_update" type="timestamp"/>
        <property name="dateDelete" column="news_date_delete" type="timestamp"/>
    </class>
</hibernate-mapping>

Por último os muestro la tabla news de la base de datos:

No hay comentarios:

Publicar un comentario