Duvida Mapear Enum com Hibernate

5 respostas
R

Estou com problema em usar Enum, com hibernate. Seguindo site http://community.jboss.org/wiki/Java5StringValuedEnumUserType

Criei minha interface:
public interface StringValuedEnum {    
    
    /**
     * Current string value stored in the enum.
     * @return string value.
     */
    public String getValue();
    
}
A classe Reflect:
public class StringValuedEnumReflect {
    
    /**
     * Don't let anyone instantiate this class.
     * @throws UnsupportedOperationException Always.
     */
    private StringValuedEnumReflect() {
        throw new UnsupportedOperationException("This class must not be instanciated.");
    }
    
    /**
     * All Enum constants (instances) declared in the specified class. 
     * @param enumClass Class to reflect
     * @return Array of all declared EnumConstants (instances).
     */
    private static <T extends Enum<T>> T[] 
            getValues(Class<T> enumClass){
        return enumClass.getEnumConstants();
    }
    
    /**
     * All possible string values of the string valued enum.
     * @param enumClass Class to reflect.
     * @return Available string values.
     */
    public static <T extends Enum<T> & StringValuedEnum> String[] 
            getStringValues(Class<T> enumClass){ 
        T[] values = getValues(enumClass);
        String[] result = new String[values.length];
        for (int i=0; i<values.length; i++){
            result[i] = values[i].getValue();
        }
        return result;
    }
    
    /**
     * Name of the enum instance which hold the especified string value.
     * If value has duplicate enum instances than returns the first occurency.
     * @param enumClass Class to inspect.
     * @param value String.
     * @return name of the enum instance.
     */
    public static <T extends Enum<T> & StringValuedEnum> String 
            getNameFromValue(Class<T> enumClass, String value){
        T[] values = getValues(enumClass);
        for (T v : values){
            if (v.getValue().equals(value)){
                return v.name();
            }
        }
        return "";
    }
    
}
A Classe EnumType:
public class StringValuedEnumType <T extends Enum<T> & StringValuedEnum> 
        implements EnhancedUserType, ParameterizedType{
    
    /**
     * Enum class for this particular user type.
     */
    private Class<T> enumClass;
 
    /**
     * Value to use if null.
     */
    private String defaultValue;
    
    /** Creates a new instance of ActiveStateEnumType */
    public StringValuedEnumType() {
    }
    
    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enum");
        try {
            enumClass = (Class<T>) Class.forName(enumClassName).asSubclass(Enum.class).
                    asSubclass(StringValuedEnum.class); //Validates the class but does not eliminate the cast
        } catch (ClassNotFoundException cnfe) {
            throw new HibernateException("Enum class not found", cnfe);
        }
 
        setDefaultValue(parameters.getProperty("defaultValue"));
    }
 
    public String getDefaultValue() {
        return defaultValue;
    }
    
    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }
    
    /**
     * The class returned by <tt>nullSafeGet()</tt>.
     * @return Class
     */
    public Class returnedClass() {
        return enumClass;
    }
 
    public int[] sqlTypes() {
        return new int[] { Types.VARCHAR };
    }
    
    public boolean isMutable() {
        return false;
    }
 
    /**
     * Retrieve an instance of the mapped class from a JDBC resultset. Implementors
     * should handle possibility of null values.
     *
     * @param rs a JDBC result set
     * @param names the column names
     * @param owner the containing entity
     * @return Object
     * @throws HibernateException
     * @throws SQLException
     */
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
            throws HibernateException, SQLException {
        String value = rs.getString( names[0] );
        if (value==null) {
            value = getDefaultValue();
            if (value==null){ //no default value
                return null;
            } 
        }
        String name = getNameFromValue(enumClass, value);
        Object res = rs.wasNull() ? null : Enum.valueOf(enumClass, name);
        
        return res;
    }
 
    /**
     * Write an instance of the mapped class to a prepared statement. Implementors
     * should handle possibility of null values. A multi-column type should be written
     * to parameters starting from <tt>index</tt>.
     *
     * @param st a JDBC prepared statement
     * @param value the object to write
     * @param index statement parameter index
     * @throws HibernateException
     * @throws SQLException
     */   
    public void nullSafeSet(PreparedStatement st, Object value, int index)
    throws HibernateException, SQLException {
        if (value==null) {
            st.setNull(index, Types.VARCHAR);
        } else {
            st.setString( index, ((T) value).getValue() );
        }
    }
    
    public Object assemble(Serializable cached, Object owner)
            throws HibernateException {
        return cached;
    }
    
    public Serializable disassemble(Object value) throws HibernateException {
        return (Enum) value;
    }
        
    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }
 
    public boolean equals(Object x, Object y) throws HibernateException {
        return x==y;
    }
    
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }
 
    public Object replace(Object original, Object target, Object owner)
            throws HibernateException {
        return original;
    }
 
    public String objectToSQLString(Object value) {
        return '\'' + ((T) value).getValue() + '\'';
    }
    
    public String toXMLString(Object value) {
        return ((T) value).getValue();
    }
 
    public Object fromXMLString(String xmlValue) {
        String name = getNameFromValue(enumClass, xmlValue);
        return Enum.valueOf(enumClass, name);
    }
        
}
E meu Enum:
public enum Status implements StringValuedEnum{
    

    Ativo("A"),
    
    Inativo("I");
 
    private final String status;
    
    ActiveState(final String status){
        this.status = status;
    }
 
    public String getValue() {
        return this.status;
    }
    
}

Como que eu mapearia por anotação minha classe:

Seria Assim:
@Enumerated(EnumType.STRING)
	@Column(name = "IDN_STATUS", columnDefinition = "char(1)")
	private Status status;

5 Respostas

V

Fala ae cara… quando usei enum com hibernate, eu fiz com mapeando por arquivos hbm.xml

Vou postar aqui que talves te ajude…

ProjetoTarefa.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	
	<hibernate-mapping package="modelo">
		
		<typedef name="enum" class="util.EnumUserType">
			<param name="classeEnum">enums.StatusTarefa</param>
		</typedef>
		
		<class name="modelo.ProjetoTarefa" table="projetotarefa">
															 
			<composite-id name="chaveComposta" class="modelo.ProjetoTarefaId" >
				
				<key-many-to-one name="projeto" 
								 column="idprojeto" 
								 class="modelo.Projeto" />
				
				<key-many-to-one name="tarefa" 
								 column="idtarefa" 
								 class="modelo.Tarefa" />
			</composite-id>
			
			<property name="status" column="status" type="enum" />
			<property name="dataCriacao" column="data" type="date" />
			
		</class>
	</hibernate-mapping>
R
vitorfarias:
Fala ae cara.... quando usei enum com hibernate, eu fiz com mapeando por arquivos hbm.xml

Vou postar aqui que talves te ajude...

ProjetoTarefa.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	
	<hibernate-mapping package="modelo">
		
		<typedef name="enum" class="util.EnumUserType">
			<param name="classeEnum">enums.StatusTarefa</param>
		</typedef>
		
		<class name="modelo.ProjetoTarefa" table="projetotarefa">
															 
			<composite-id name="chaveComposta" class="modelo.ProjetoTarefaId" >
				
				<key-many-to-one name="projeto" 
								 column="idprojeto" 
								 class="modelo.Projeto" />
				
				<key-many-to-one name="tarefa" 
								 column="idtarefa" 
								 class="modelo.Tarefa" />
			</composite-id>
			
			<property name="status" column="status" type="enum" />
			<property name="dataCriacao" column="data" type="date" />
			
		</class>
	</hibernate-mapping>

Mas Realmente preciso fazer isto por anotação. infelizmente e não estou conseguindo

dieego_

Olá

Quando eu preciso mapear enum no hibernate eu uso apenas isso:

com isto ele gravará a string completa do enum.
Eu entendo sua preocupação com esta informação redundante na tabela, mais acho que a perda de tempo tentando bolar outra coisa não compensa. Acredito que o ganho em performance e espaço no banco de dados é imperceptível.

R

dieego_:
Olá

Quando eu preciso mapear enum no hibernate eu uso apenas isso:

com isto ele gravará a string completa do enum.
Eu entendo sua preocupação com esta informação redundante na tabela, mais acho que a perda de tempo tentando bolar outra coisa não compensa. Acredito que o ganho em performance e espaço no banco de dados é imperceptível.

Até poderia utilizar isto… desde que não fosse um banco que já esteje rodando desta forma.

CharlesAlves

cria um enun com uma variável interna do tipo int contendo o id da tabela que vai ser feita a referencia

publuc enun enumerated{

   ITEM1(1), ITEM2(2)

   private int item;

   private enumerated(int item){
      this.item = item;
   }

   public int getItem(){
      return this.item;
   }

}

e faz o mapeamento com o annotation

Criado 9 de agosto de 2011
Ultima resposta 21 de set. de 2011
Respostas 5
Participantes 4