Enum avançado e difícil. Alguém?

4 respostas
saoj

Coloquei o tópico para ver se algum guru me ajuda aqui.

Tenho uma classe que descreve um tipo no banco de dados. O que quero fazer é suportar um tipo Enum, ou seja:

:arrow: Quando lê do banco, converte a String para o Enum correspondente, ou seja, se leu "F", converte para o enum Category.Type.F.

:arrow: Quando vai inserir no banco, converte o Enum para a String correspondente, ou seja, se o enum é Category.Type.F converte para "F".

Abaixo está a minha classe para Strings. Como eu escreveria algo similar para Enums ?

A dificuldade é que eu tenho que passar a classe do meu Enum para dentro do meu EnumType para poder converter de String para Enum e vice versa. Não sei se passo via Generics (Ex: EnumType<Category.Type>) e não sei se passa via parametro do constructor (Ex: new EnumType(Category.Type.class)).

public class StringType implements DBType {
	
	public String toString() {
		
		return this.getClass().getSimpleName();
	}
	
	public Object getFromResultSet(ResultSet rset, int index) throws SQLException {
		
		return rset.getString(index);
	}

	public Object getFromResultSet(ResultSet rset, String field) throws SQLException {
		
		return rset.getString(field);
	}
	
	
	public Class&lt;? extends Object&gt; getTypeClass() {
		
		return String.class;
	}
	
	public void bindToStmt(PreparedStatement stmt, int index, Object value) throws SQLException {
		
		if (value == null) {
		
			stmt.setString(index, null);
			
		} else if (value instanceof String) {
			
			String s = (String) value;
		
			stmt.setString(index, s);
			
		} else {
			
			throw new IllegalArgumentException("value is not a string!");
		}
		
	}
}

4 Respostas

duardor

Dê uma olhada no TypeHandler para enums do iBatis, ele faz mais ou menos isso dai que vc quer, passando o tipo no construtor… Deve dar pra vc basear como exemplo
http://www.docjar.com/html/api/com/ibatis/sqlmap/engine/type/EnumTypeHandler.java.html
E pra transformar de Enum para String vc nao precisa saber da classe, basta um .name() (ou .toString() no default) com a instancia que vc tem em mãos certo?

saoj

duardor:
Dê uma olhada no TypeHandler para enums do iBatis, ele faz mais ou menos isso dai que vc quer, passando o tipo no construtor… Deve dar pra vc basear como exemplo
http://www.docjar.com/html/api/com/ibatis/sqlmap/engine/type/EnumTypeHandler.java.html
E pra transformar de Enum para String vc nao precisa saber da classe, basta um .name() (ou .toString() no default) com a instancia que vc tem em mãos certo?

Muito obrigado! Ajudou bastante. Dá para perceber que o MentaBean é muito parecido com o iBatis. :wink:

G

putz os caras estão num nível completamente diferente do meu xD, to pelejando pra entender esse negócio! mas um dia chego lá!!!

saoj

Tanto o Hibernate quanto o iBatis não usam Generics direito. Pelo menos é o que parece. O iBatis ignora generics e o Hibernate faz algo assim:

private Class&lt;? extends Enum&gt; enumClass;

Quando eu acho que deveria ser:

private Class&lt;? extends Enum&lt;?&gt;&gt; enumClass;

Fonte: http://www.docjar.com/html/api/org/hibernate/type/EnumType.java.html

Usando a declaração correta logo acima, eu estou recebendo um warning de generics pentelho aqui:

return Enum.valueOf((Class) enumType, s);

Como vc pode ver estou tendo que fazer um cast se não não rola. O código completo está abaixo.

Alguém saberia dizer se é possível e se for como fazer essa classe ficar redondinha com generics para enums? Parece que nem os caras do iBatis e Hibernate sabem fazer isso. :expressionless:

public class EnumType implements DBType {
	
	private final Class&lt;? extends Enum&lt;?&gt;&gt; enumType;
	
	public EnumType(Class&lt;? extends Enum&lt;?&gt;&gt; enumType) {
		
		this.enumType = enumType;
	}
	
	public String toString() {
		
		return this.getClass().getSimpleName() + ": " + enumType.getSimpleName();
	}
	
	public Object getFromResultSet(ResultSet rset, int index) throws SQLException {
		
		String s = rset.getString(index);
		
		if (s == null) return null;
		
		return Enum.valueOf((Class) enumType, s);

	}

	public Object getFromResultSet(ResultSet rset, String field) throws SQLException {
		
		String s = rset.getString(field);
		
		if (s == null) return null;
		
		return Enum.valueOf((Class) enumType, s);

	}
	
	public Class&lt;? extends Object&gt; getTypeClass() {
		
		return enumType;
	}
	
	public void bindToStmt(PreparedStatement stmt, int index, Object value) throws SQLException {
		
		if (value == null) {
		
			stmt.setString(index, null);
			
		} else if (value instanceof Enum && value.getClass().isAssignableFrom(enumType)) {
			
			String s = value.toString();
		
			stmt.setString(index, s);
			
		} else {
			
			throw new IllegalArgumentException("value is not a enum!");
		}
		
	}
Criado 13 de março de 2011
Ultima resposta 15 de mar. de 2011
Respostas 4
Participantes 3