Problema ao persistir class com list Enum

26 respostas
tebosoftware

Bom dia pessoal

Ao tentar persistir a minha classe Candidato, da um erro no hibernate de:

Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum
	at org.hibernate.type.EnumType.nullSafeSet(EnumType.java:123)
	at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:155)
	at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:867)
	at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1257)
	at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:58)
	at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:279)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
	at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1210)
	at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:986)
	at com.sun.enterprise.container.common.impl.EntityManagerWrapper.flush(EntityManagerWrapper.java:418)
	at empresa.package.dao.AbstractDAO.gravar(AbstractDAO.java:60)
	... 91 more

A minha classe é

Candidato.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.modelo.endereco.Endereco;
import empresa.package.modelo.usuario.TipoUsuario;
import empresa.package.modelo.usuario.Usuario;
import empresa.package.modelo.vaga.Funcao;
import empresa.package.util.Util;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
import org.joda.time.DateTime;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Entity
@Table(schema = "AcifEmpregos")
public class Candidato extends AbstractModelo implements Usuario {

    private static final int NOME_LENGTH = 60;
    private static final int EMAIL_LENGTH = 100;
    private static final int CPF_LENGTH = 11;
    private static final int SENHA_LENGTH = 32;
    private static final int RG_LENGTH = 20;
    private static final int DEFICIENCIA_LENGTH = 100;
    private static final int HABILIDADESQUALIFICACOES_LENGTH = 1024;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(nullable = false, length = NOME_LENGTH)
    private String nome;
    @Embedded
    private Endereco endereco;
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dataNascimento;
    @Enumerated(EnumType.STRING)
    private Sexo sexo;
    @Enumerated(EnumType.STRING)
    private EstadoCivil estadoCivil;
    @Column(length = EMAIL_LENGTH)
    private String email;
    @Column(length = CPF_LENGTH)
    private String cpf;
    @Column(length = SENHA_LENGTH)
    private String senha;
    @Column(length = RG_LENGTH)
    private String rg;
    private boolean possuiDeficiencia;
    @Column(length = DEFICIENCIA_LENGTH)
    private String deficiencia;
    @ElementCollection(targetClass = Cnh.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoCHN")
    @Enumerated(EnumType.STRING)
    private List<Cnh> cnh;
    @ElementCollection(targetClass = Periodo.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoPeriodo")
    @Enumerated(EnumType.STRING)
    private List<Periodo> periodo;
    private boolean disponivelViagem;
    private boolean salarioCombinar;
    private double pretensaoSalarial;
    @Column(length = HABILIDADESQUALIFICACOES_LENGTH)
    private String habilidadesQualificacoes;
    @ElementCollection(targetClass = Curso.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoCursos")
    private List<Curso> cursos;
    @OneToMany(mappedBy = "candidato")
    private List<ExperienciaProfissional> experienciaProfissionais;
    @ElementCollection(targetClass = Formacao.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoFormacao")
    private List<Formacao> formacoes;
    @ManyToMany
    @JoinTable(schema = "AcifEmpregos", name = "CandidatoFuncaoInteresse")
    private List<Funcao> funcoesInteresse;
    @ElementCollection(targetClass = Telefone.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoTelefone")
    private List<Telefone> telefones;
    @ElementCollection(targetClass = IdiomaCandidato.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoIdioma")
    private List<IdiomaCandidato> idiomas;

    //gets, sets, hashcode e equals removido
}

Endereco.java

package empresa.package.modelo.endereco;

import empresa.package.modelo.AbstractModelo;
import empresa.package.util.Util;
import java.io.Serializable;
import java.util.regex.Pattern;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.ManyToOne;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Embeddable
public class Endereco extends AbstractModelo {

    private static final int LOGRADOURO_LENGTH = 50;
    private static final int COMPLEMENTO_LENGTH = 20;
    private static final int BAIRRO_LENGTH = 30;
    private static final int CIDADE_LENGTH = 50;
    private static final int CEP_LENGTH = 8;
    private Integer seqEnderecoGeral;
    @Column(nullable = false, length = LOGRADOURO_LENGTH)
    private String logradouro;
    private Integer numero;
    @Column(length = COMPLEMENTO_LENGTH)
    private String complemento;
    @Column(nullable = false, length = BAIRRO_LENGTH)
    private String bairro;
    @Column(nullable = false, length = CIDADE_LENGTH)
    private String cidade;
    @ManyToOne
    private Estado estado;
    @Column(nullable = false, length = CEP_LENGTH)
    private String cep;

    //gets, sets, hashcode e equals removido
}

Sexo.java

package empresa.package.modelo.candidato;

/**
 *
 * @author thales @data 25/06/2012
 */
public enum Sexo {

    MASCULINO("Masculino"),
    FEMININO("Feminino");
    private String descricao;

    public String getDescricao() {
        return descricao;
    }

    private Sexo(String descricao) {
        this.descricao = descricao;
    }
}

EstadoCivil.java

package empresa.package.modelo.candidato;

/**
 *
 * @author thales @data 25/06/2012
 */
public enum EstadoCivil {

    SOLTEIRO("Solteiro (a)"),
    CASADO("Casado (a)"),
    DIVORCIADO("Divorciado (a)"),
    VIUVO ("Viúvo (a)"),
    UNIAO_ESTAVEL("União Estável");
    private String descricao;

    public String getDescricao() {
        return descricao;
    }

    private EstadoCivil(String descricao) {
        this.descricao = descricao;
    }
}

Cnh.java

package empresa.package.modelo.candidato;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
public enum Cnh {

    A("A"), B("B"), C("C"), D("D"), E("E");
    private String descricao;

    private Cnh(String descricao) {
        this.descricao = descricao;
    }

    public String getDescricao() {
        return descricao;
    }
}

Periodo.java

package empresa.package.modelo.candidato;

/**
 *
 * @author thales @data 25/06/2012
 */
public enum Periodo {

    MANHA("Manhã"),
    TARDE("Tarde"),
    NOITE("Noite");
    private String descricao;

    public String getDescricao() {
        return descricao;
    }

    private Periodo(String descricao) {
        this.descricao = descricao;
    }
}

Curso.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.util.Util;
import java.io.Serializable;
import javax.persistence.*;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Embeddable
public class Curso extends AbstractModelo {

    private static final int DESCRICAO_LENGTH = 60;
    @Column(nullable = false, length = DESCRICAO_LENGTH)
    private String descricao;
    private Integer mesInicial;
    private Integer anoInicial;
    private Integer mesFinal;
    private Integer anoFinal;
    private Integer cargaHoraria;
    private boolean concluido;

    //gets, sets, hashcode e equals removido
}

ExperienciaProfissional.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.modelo.endereco.Endereco;
import empresa.package.modelo.vaga.Area;
import empresa.package.modelo.vaga.Cargo;
import empresa.package.modelo.vaga.Funcao;
import empresa.package.util.Util;
import java.io.Serializable;
import java.util.List;
import javax.persistence.*;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Entity
@Table(schema = "AcifEmpregos", name = "CandidatoExpProf")
public class ExperienciaProfissional extends AbstractModelo {

    private static final int EMPRESA_LENGTH = 60;
    private static final int RESPONSAVEL_LENGTH = 60;
    private static final int DESCRICAO_FUNCOES_LENGTH = 1024;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @ManyToOne
    private Candidato candidato;
    @Column(nullable = false, length = EMPRESA_LENGTH)
    private String empresa;
    @Column(nullable = false, length = RESPONSAVEL_LENGTH)
    private String responsavel;
    @Embedded
    private Endereco endereco;
    private Integer mesInicial;
    private Integer anoInicial;
    private Integer mesFinal;
    private Integer anoFinal;
    private boolean empregoAtual;
    @Column(nullable = false, length = DESCRICAO_FUNCOES_LENGTH)
    private String descricaoFuncoes;
    @ManyToOne(cascade = CascadeType.ALL, optional = false)
    private Area area;
    @ManyToMany
    @JoinTable(schema = "AcifEmpregos", name = "CandidatoExpProfFuncao")
    private List<Funcao> funcao;
    @ManyToOne(cascade = CascadeType.ALL, optional = false)
    private Cargo cargo;
    @ElementCollection(targetClass = Telefone.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoExpProfTelefone")
    private List<Telefone> telefones;

    //gets, sets, hashcode e equals removido
}

Formacao.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.modelo.endereco.Estado;
import empresa.package.modelo.vaga.Area;
import empresa.package.util.Util;
import java.io.Serializable;
import javax.persistence.*;

/**
 *
 * @author thales
 * @data 26/06/2012
 */
@Embeddable
public class Formacao extends AbstractModelo {

    private static final int DESCRICAO_LENGTH = 100;
    private static final int INSTITUICAO_LENGTH = 100;
    private static final int CIDADE_LENGTH = 50;
    @Column(length = DESCRICAO_LENGTH, nullable = false)
    private String descricao;
    private Integer mesInicial;
    private Integer anoInicial;
    private Integer mesFinal;
    private Integer anoFinal;
    private boolean concluido;
    @Column(length = INSTITUICAO_LENGTH, nullable = false)
    private String instituicao;
    @Column(length = CIDADE_LENGTH, nullable = false)
    private String cidade;
    @ManyToOne
    private Estado estado;
    @Enumerated(EnumType.STRING)
    private Grau grau;
    @ManyToOne
    private Area area;

    //gets, sets, hashcode e equals removido
}

Funcao.java

package empresa.package.modelo.vaga;

import empresa.package.modelo.AbstractModelo;
import empresa.package.util.Util;
import java.io.Serializable;
import javax.persistence.*;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Entity
@Table(schema = "AcifEmpregos")
public class Funcao extends AbstractModelo {

    private static final int DESCRICAO_LENGTH = 100;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(length = DESCRICAO_LENGTH, nullable = false)
    private String descricao;
    @ManyToOne
    private Area area;

    //gets, sets, hashcode e equals removido
}

Telefone.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.util.Util;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Embeddable
public class Telefone extends AbstractModelo {

    private static final int NUMERO_TAMANHO = 20;
    @Column(nullable = false, length = NUMERO_TAMANHO)
    private String numero;
    @Enumerated(EnumType.STRING)
    private TipoTelefone tipoTelefone;

    //gets, sets, hashcode e equals removido
}

IdiomaCandidato.java

package empresa.package.modelo.candidato;

import empresa.package.modelo.AbstractModelo;
import empresa.package.modelo.endereco.Estado;
import empresa.package.modelo.vaga.Idioma;
import empresa.package.util.Util;
import java.io.Serializable;
import javax.persistence.*;

/**
 *
 * @author thales
 * @data 25/06/2012
 */
@Embeddable
public class IdiomaCandidato extends AbstractModelo {

    private static final int INSTITUICAO_LENGTH = 100;
    private static final int CIDADE_LENGTH = 50;
    @ManyToOne(optional = false)
    private Idioma idioma;
    @Enumerated(EnumType.STRING)
    private Nivel nivel;
    private Integer mesInicial;
    private Integer anoInicial;
    private Integer mesFinal;
    private Integer anoFinal;
    private boolean concluido;
    @Column(length = INSTITUICAO_LENGTH, nullable = false)
    private String instituicao;
    @Column(length = CIDADE_LENGTH, nullable = false)
    private String cidade;
    @ManyToOne
    private Estado estado;

    //gets, sets, hashcode e equals removido
}

26 Respostas

Hebert_Coelho

Mano, uma dica? Não poste esse monte de código. Fica dificil de ler. Começa postando apenas a mensagem de erro e, no seu caso, qual o enum que deu erro.

Você sabe falar qual?

tebosoftware

Bom dia

Desculpe se incomodou a questão dos códigos, achei que fosse ajudar.

Pelo que eu consegui simular, a falha acontece nos enum que estão em list.

tmvolpato

esses ENUMS que vc criou vão ser colocados em comboBox certo?

não precisa fazer isso

@ElementCollection(targetClass = Cnh.class) @CollectionTable(schema = "AcifEmpregos", name = "CandidatoCHN") @Enumerated(EnumType.STRING) private List<Cnh> cnh;

faça isso

@Enumerated(EnumType.STRING) @Column(name="CNH") //Apenas por costume e deixa a coluna do bd com nome que eu anotei private Cnh cnh;

Está usando JSF?

tebosoftware

Na realidade eu preciso que sejam uma lista pois a pessoa poderá escolher vários.

tmvolpato

dessa maneira que vc esta tentando eu nao consegui tbm
ai fiz de outra maneira, sem utilizar enum para esse caso

se quiser posso te passar

tebosoftware

Bom ai complica.

A única maneira seria pegar e criar classes embedded com somente este atributo?

pois eu coloquei com marcação @Transient e funcionou a gravação sem eles

tmvolpato
tebosoftware:
Bom ai complica.

A única maneira seria pegar e criar classes embedded com somente este atributo?

pois eu coloquei com marcação @Transient e funcionou a gravação sem eles

fiz de outra maneira

Segue abaixo

Na minha aplicaçao nao preciso selecionar vários entao optei por usar dessa maneira

@Column(name=&quot;CNH&quot;, length=25)
private String[] cnh;
public String getCnhFormat(){
		String cnhf = &quot;&quot;;
		if (getCnh() != null){
			for(int i = 0; i &lt; getCnh().length; i++){
				ctf += getCnh()[i];
				if (i &lt; getCnh().length -1){
					cnhf += &quot;, &quot;;
				}
			}
		}
		return cnhf;
	}
exemplo para exibir
&lt;p:selectManyCheckbox id="cnh" 
                                          value="#{testeFace.selecionado.cnh}" &gt;
	        &lt;f:selectItem itemLabel="Carta A" itemValue="Carta A" /&gt;  
                &lt;f:selectItem itemLabel="Carta B" itemValue="Carta B" /&gt;  
&lt;/p:selectManyCheckbox&gt;
	  
foi como eu disse na minha aplicação ate agora so precisei selecionar varios apenas uma vez
Hebert_Coelho

Cara, eu to escrevendo um post sobre JPA e cheguei na pagina do @ElementCollection.

Olha como eu fiz e funcionou numa boa:
public enum CarBrands {
	FORD, FIAT, SUZUKI
}

import java.util.List;
import java.util.Set;

import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "person")
public class Person {

	@Id
	@GeneratedValue
	private int id;
	private String name;

	@ElementCollection
	@CollectionTable(name = "person_has_emails")
	private Set<String> emails;

	@ElementCollection
	@Enumerated(EnumType.STRING)
	private List<CarBrands> brands;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<String> getEmails() {
		return emails;
	}

	public void setEmails(Set<String> emails) {
		this.emails = emails;
	}

	public List<CarBrands> getBrands() {
		return brands;
	}

	public void setBrands(List<CarBrands> brands) {
		this.brands = brands;
	}
}
Hebert_Coelho

OBS.: Esse código é de um post que vou lançar daqui duas semanas ainda.
De primeira mão! =P

tebosoftware

Hebert

Se você olhar, o meu código está igual ao seu:

@ElementCollection(targetClass = Cnh.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoCHN")
    @Enumerated(EnumType.STRING)
    private Set&lt;Cnh&gt; cnh;
    @ElementCollection(targetClass = Periodo.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoPeriodo")
    @Enumerated(EnumType.STRING)
    private Set&lt;Periodo&gt; periodo;

a única diferença é que eu tive e colocar a anotação @CollectionTable para dar o schema e o nome da tabela.

Hebert_Coelho

tebosoftware:
Hebert

Se você olhar, o meu código está igual ao seu:

@ElementCollection(targetClass = Cnh.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoCHN")
    @Enumerated(EnumType.STRING)
    private Set&lt;Cnh&gt; cnh;
    @ElementCollection(targetClass = Periodo.class)
    @CollectionTable(schema = "AcifEmpregos", name = "CandidatoPeriodo")
    @Enumerated(EnumType.STRING)
    private Set&lt;Periodo&gt; periodo;

a única diferença é que eu tive e colocar a anotação @CollectionTable para dar o schema e o nome da tabela.

Se bem que você está utilizando Hibernate e eu fiz com EclipseLink.
As importações das anotações estão corretas? Você utiliza apenas as anotações do JPA?
Outra coisa, não seria problema da tabela não? O tipo do dado diferente?

tebosoftware

Eu estou utilizando somente JPA Annotations. E a tabela está sendo criada pelo hibernate.

Hebert_Coelho

Como você está populando esse enum antes de salvar?

tebosoftware

Crio um HashSet e adiciono os enums q eu seleciono na tela.

Hebert_Coelho

tebosoftware:
Crio um HashSet e adiciono os enums q eu seleciono na tela.
Cara, faz um teste tentando colocar como List ao invés de Set.
Tá bizarro. O.o

tebosoftware

O original era List.

Hebert_Coelho

tebosoftware:
O original era List.
Vai no forum do hibernate e posta lá (ou procure para ver se já não existe algo do tipo).
Talvez seja um bug conhecido da versão do hibernate que você está utilizando.

tebosoftware

Eu já tinha procurado, mas não achei nada parecido.

Vou dar uma olhada no forum do hibernate

tebosoftware

Acho q eu descobri o problema, a questão é o componente do primefaces selectManyCheckbox ele está me enviando uma lista de String ao invés de uma lista de Enum.

tebosoftware

É realmente a falha é do primefaces. Depois de muito debugar eu vi que o hashset que ele atribuía vinha sem tipagem (Generic) e os valores eram em String. Tive que fazer o código abaixo para resolver o problema:

public void setCnh(Set&lt;Cnh&gt; cnh) {
        if (cnh == null) {
            this.cnh = null;
        } else {
            this.cnh = Util.createSet();
            for (Object o : cnh) {
                if (o instanceof Cnh) {
                    this.cnh.add((Cnh) o);
                } else {
                    this.cnh.add(Cnh.valueOf(o.toString()));
                }
            }
        }
    }

Falow

D

tebosoftware ,

Já conseguiu resolver o problema amigo?

[]s
Diego

tebosoftware

Resolvei da maneira q eu comentei anteriormente. Mas pode ser feito também através do uso de conversores.

Hebert_Coelho

tebosoftware:
Resolvei da maneira q eu comentei anteriormente. Mas pode ser feito também através do uso de conversores.
É cara, eu acho que tem alguma coisa errada com seu código.
Enum não precisa de converter.

tebosoftware

Como eu disse, a falha está no selectManyCheckbox que ao invés de retornar uma lista de Enum retorna uma lista de String.

tebosoftware

Após resolver esse problema com relação os Enum’s, estou tendo problema com o org.hibernate.LazyInitializationException: could not initialize proxy - no Session.
Estou utilizando ambiente em EJB 3.0.

Alguém sabe solucionar?

tebosoftware

Após resolver esse problema com relação os Enum’s, estou tendo problema com o org.hibernate.LazyInitializationException: could not initialize proxy - no Session.
Estou utilizando ambiente em EJB 3.0.

Alguém sabe solucionar?

Criado 10 de outubro de 2012
Ultima resposta 11 de out. de 2012
Respostas 26
Participantes 4