Hibernate e Enum

5 respostas
L

O problema:

Vocês podem ver que tenho um atributo do tipo enum Status { ATIVO, INATIVO; }, mas o campo da minha tabela somente aceita um caracter CHAR(1).

Minha tentativa foi redefinindo o metódo toString(), executando no java puro até que funciona, quando o hibernate vai persistir o Enum ele não utiliza o método toString() e grava { ATIVO ou INATIVO} e não { A ou I }.

Alguém já implementou ou resolveu algo como isso!

Analisem os códigos abaixo:

@Entity
@Table(name="PRODUTO")
public class Produto implements Serializable {
    . . .
    @Enumerated(EnumType.STRING)
    @Column(name="STATUS", nullable = false, columnDefinition="CHAR", length=1)
    private Status status;
    . . .
    get e set
    . . .
}
public enum Status {
    ATIVO("A"), DESATIVO("D");

    private final String value;

    Status(String value) {  
        this.value = value;  
    }  

    public String value() {  
        return this.value;  
    } 

    public String toString() {
        return this.value();
    }
    
}

5 Respostas

T

Hum, o contrário de “ATIVO” é “INATIVO” e o contrário de “ATIVADO” é “DESATIVADO”.
“DESATIVO” é um verbo (“eu desativo uma bomba”), mas acho que o padrão para nomes de enums é um substantivo ou um adjetivo.

Note que o UserType, dado como exemplo, que persiste enums ( http://www.hibernate.org/265.html ) usa o método “name” (que vai retornar “ATIVO” ou “DESATIVO” - argh) e não o método “toString” para persistir enums; talvez seja necessário criar um outro UserType. OK?

L

thingol:
Hum, o contrário de “ATIVO” é “INATIVO” e o contrário de “ATIVADO” é “DESATIVADO”.
“DESATIVO” é um verbo (“eu desativo uma bomba”), mas acho que o padrão para nomes de enums é um substantivo ou um adjetivo.

Note que o UserType, dado como exemplo, que persiste enums ( http://www.hibernate.org/265.html ) usa o método “name” (que vai retornar “ATIVO” ou “DESATIVO” - argh) e não o método “toString” para persistir enums; talvez seja necessário criar um outro UserType. OK?

Examinei o código do link, mas não funcionou, como o método name() é final, aí que está o problema, não consigo redefini-lo!

T

O método “name” é final e não pode ser redefinido, então você teria de ter um outro UserType, cujo código é o mesmo exceto pelo fato de você ter de trocar “name” por “toString”.

D

Oi Leonardo!

Já resolveu seu problema com user type?
Se não me passa outro post acho que tenho uma solução pra você.

R

Desculpem reviver o tópico, mas como não achei a solução estou postando uma alternativa.

JPA poderia fornecer algo do tipo: @Enumerated(EnumType.Character)
mas como não existe consegui fazer da seguinte forma:

*Lembrando que isso é para usar Enum quando o banco estiver com Char

[size=18]Primeiro cria o Enum[/size]

public enum SituacaoSistemaEnum {

	ENTRADA("E"), SAIDA("S");

	private String value;

	SituacaoSistemaEnum(String value) {
		this.value = value;
	}
	
	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	@Override
	public String toString() {
		switch (this) {
		case SAIDA:
			return "Saida";

		case ENTRADA:
			return "Entrada";

		default:
			return "---";
		}
	}

	public String getI18n() {
		switch (this) {
		case SAIDA:
			return "sistema.situacaoSistemaEnum.entrada";

		case ENTRADA:
			return "sistema.situacaoSistemaEnum.saida";

		default:
			return "---";
		}
	}
	
	public static SituacaoSistemaEnum fromString(String value) {
		
		if (value == null) 
			throw new IllegalArgumentException("value não pode ser nulo");
		
		return value.equalsIgnoreCase("ENTRADA") ?  ENTRADA : SAIDA;
	}


	public static SituacaoSistemaEnum recreateEnum(String value) {
		SituacaoSistemaEnum enumVal = null;

		if (value != null) {
			if (value.equalsIgnoreCase("E"))
				enumVal = SituacaoSistemaEnum.ENTRADA;
			else if (value.equalsIgnoreCase("S"))
				enumVal = SituacaoSistemaEnum.SAIDA;
		}

		return enumVal;
	}

	public String recreateString() {
		return value;
	}



}

[size=18]Implementa as interfaces UserType, ParameterizedType:[/size]

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

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import org.springframework.util.ObjectUtils;

public class AssociacaoType implements UserType, ParameterizedType {

	private Class enumClass;
	private Method recreateEnumMthd;
	private Method recreateStringMthd;

	public int[] sqlTypes() {
		return new int[] { Types.CHAR };
	}

	public Class returnedClass() {
		return enumClass;
	}

	public boolean equals(Object x, Object y) throws HibernateException {
		return ObjectUtils.nullSafeEquals(x, y);
	}

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

	public Object nullSafeGet(ResultSet rs, String[] names,
			SessionImplementor session, Object owner)
			throws HibernateException, SQLException {

		String value = rs.getString(names[0]);
		Object returnVal = null;

		if (value == null)
			return null;
		else {
			try {
				returnVal = recreateEnumMthd.invoke(enumClass,
						new Object[] { value });
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		return returnVal;
	}

	public void nullSafeSet(PreparedStatement st, Object value, int index,
			SessionImplementor session) throws HibernateException, SQLException {
		String prepStmtVal = null;

		if (value == null) {
			st.setObject(index, null);
		} else {
			try {
				prepStmtVal = (String) recreateStringMthd.invoke(value,
						new Object[] {});
				st.setString(index, prepStmtVal);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}

	}

	public Object deepCopy(Object value) throws HibernateException {
		if (value == null)
			return null;
		else {
			SituacaoSistemaEnum enumVal = (SituacaoSistemaEnum) value;
			return SituacaoSistemaEnum.recreateEnum(enumVal.getValue());
		}

	}

	public boolean isMutable() {
		return false;
	}

	public Serializable disassemble(Object value) throws HibernateException {
		Object deepCopy = deepCopy(value);

		if (!(deepCopy instanceof Serializable))
			return (Serializable) deepCopy;

		return null;

	}

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

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

	@SuppressWarnings("unchecked")
	public void setParameterValues(Properties parameters) {
		if (parameters != null) {
			String enumMthd = parameters.getProperty("recreateEnumMthd");
			String strMthd = parameters.getProperty("recreateStringMthd");
			String className = parameters.getProperty("enumClassName");
			Class<?> returnType = null;

			try {
				enumClass = Class.forName(className);
				recreateStringMthd = enumClass.getMethod(strMthd,
						new Class[] {});
				returnType = recreateStringMthd.getReturnType();
				recreateEnumMthd = enumClass.getMethod(enumMthd,
						new Class[] { returnType });
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			}
		}

	}

}

[size=18]Entidade mapeada:[/size]

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Type;

@Entity
@Table(name = "ASSOCIACAO")
public class EntidadeTeste implements Serializable {


	@Id
	@Column
	private Long id;

	@Type(type = "br.com.client.entity.type.AssociacaoType", parameters = {
			@Parameter(name = "enumClassName", value = "br.com.client.enumerators.SituacaoSistemaEnum"),
			@Parameter(name = "recreateEnumMthd", value = "recreateEnum"),
			@Parameter(name = "recreateStringMthd", value = "recreateString") })
	@Column(name = "TP_ASSOCIACAO", nullable = false)
	private SituacaoSistemaEnum tpAssociacao;

	//get e set

}
Criado 9 de janeiro de 2009
Ultima resposta 21 de set. de 2012
Respostas 5
Participantes 4