problema ao persistir entidade com campo tipo enum

Java

17/08/2010

opa td bom..
 
seguinte.. to fazendo uma app de cadastro de curriculo com hibernate e jsf mas to enroscado em uma parte do cadastro... a minha idéia é cadastrar idioma e nivel de conhecimanto usando enum.. então eu tenho a classe Idioma que possui nome e nivel (ambos tipo enum).. a classe Curriculo possui relacionamento one-to-many com a classe Idioma, pois um curriculo possui vários idiomas.. como a classe Idioma possui nome do idioma e nível de conhecimento.. a classe curriculo possui uma lista  de idiomas.. mas não estou conseguindo finalizar essa idéia.. vou postar os código e a msg de erro na sequencia:
 
hibernate xml da classe Idioma e Curriculo:
 
<hibernate-mapping>
    <typedef class="br.com.working.entity.StringEnumUserType" name="nivel">
        <param name="enumClassName">br.com.working.entity.Nivel</param>
    </typedef>
    <typedef class="br.com.working.entity.StringEnumUserType" name="nome">
        <param name="enumClassName">br.com.working.entity.Nome</param>
    </typedef>
    <class name="br.com.working.entity.Idioma" table="idioma">
        <id name="id" column="idioma">
            <generator class="sequence">
                <param name="sequence">idioma_seq</param>
            </generator>
        </id>
 
        <property name="nivel" column="nivel" type="nivel" not-null="true" update="false" access="field" />
        <property name="nome" column="nome" type="nome" not-null="true" update="false" access="field" />
        <many-to-one name="curriculo" class="br.com.working.entity.Curriculo" column="curriculo" />
    </class>
</hibernate-mapping>
 
<hibernate-mapping>
    <class name="br.com.working.entity.Curriculo" table="curriculo">
        <id name="id" column="pessoa">
            <generator class="foreign">
                <param name="property">pessoa</param>
            </generator>
        </id>
        <property name="objetivo" column="objetivo" />
        <one-to-one name="pessoa" class="br.com.working.entity.Pessoa" constrained="true" />
        <bag name="ep" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.ExperienciaProfissional" />
        </bag>
        <bag name="fa" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.FormacaoAcademica" />
        </bag>
        <bag name="idioma" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.Idioma" />
        </bag>
    </class>
</hibernate-mapping>
 
 
trecho método do managed bean que prepara a página  
(aqui existe a classe Pessoa p que é dona do curriculo)
o nivel de idioma vem da página jsf:
 
    public String preparaCurriculo3 () {
        
        curriculo = curDao.getCurriculo(p.getCurriculo().getId());
        listIdioma = curDao.getIdioma(curriculo.getId());
        
        if (listIdioma.size() > 0)  
        {
            idioma1 = listIdioma.get(0);  
        }
        else {
            idioma1 = new Idioma();
            idioma1.setNome(Nome.INGLES);
        }
        
        if (listIdioma.size() > 1) {
            idioma2 = listIdioma.get(1);  
        }
        else {
            idioma2 = new Idioma();
            idioma2.setNome(Nome.ESPANHOL);
        }
        
        listIdioma.removeAll(listIdioma);
        listIdioma.add(idioma1);
        listIdioma.add(idioma2);
        
        idioma1.setCurriculo(curriculo);
        idioma2.setCurriculo(curriculo);
        curriculo.setIdioma(listIdioma);
 
        p.setCurriculo(curriculo);
        curriculo.setPessoa(p);
 
        return "addCurriculo3";
    }
 
quando vou salvar a página vem o seguinte erro:
 
org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.working.entity.Idioma.nivel
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
 
alguém sabe o que está errado?
Fabiano Souza

Fabiano Souza

Curtidas 0

Respostas

Dyego Carmo

Dyego Carmo

17/08/2010

Opa !

Pelo que eu Estou vendo... a classe br.com.working.entity.Idioma até existe , porem a sua propriedade nivel (dentro de  br.com.working.entity.Idioma) está NULL , poderia confirmar ?(use um System.out.println(""))


GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

coloquei a seguinte linha:

System.out.println(p.getCurriculo().getIdioma().get(1).getNivel());
e imprimiu: INTERMEDIARIO

desconfio que seja um erro no mapeamento ou o campo enum no banco.

eu to usando ORACLE e ae vai a pergunta: que tipo deve ser meu campo enum no oracle? eu coloquei VARCHAR2(255)
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Opa , poderia colar as classes java aqui ? estou com duvidas...

Já tentou realizar este mapeamento utilizando anotações ? é até mais facil !

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

arquivo Curriculo do hibernate:
 
<hibernate-mapping>
    <class name="br.com.working.entity.Curriculo" table="curriculo">
        <id name="id" column="pessoa">
            <generator class="foreign">
                <param name="property">pessoa</param>
            </generator>
        </id>
        <property name="objetivo" column="objetivo" />
        <one-to-one name="pessoa" class="br.com.working.entity.Pessoa" constrained="true" />
        <bag name="ep" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.ExperienciaProfissional" />
        </bag>
        <bag name="fa" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.FormacaoAcademica" />
        </bag>
        <bag name="idioma" cascade="all" inverse="true">
            <key column="curriculo" not-null="true" />
            <one-to-many class="br.com.working.entity.Idioma" />
        </bag>
    </class>
</hibernate-mapping>
 
arquivo Idioma do hibernate:
 
<hibernate-mapping>
    <typedef class="br.com.working.entity.StringEnumUserType" name="nivel">
        <param name="enumClassName">br.com.working.entity.Nivel</param>
    </typedef>
    <typedef class="br.com.working.entity.StringEnumUserType" name="nome">
        <param name="enumClassName">br.com.working.entity.Nome</param>
    </typedef>
    <class name="br.com.working.entity.Idioma" table="idioma">
        <id name="id" column="idioma">
            <generator class="sequence">
                <param name="sequence">idioma_seq</param>
            </generator>
        </id>
 
        <property name="nivel" column="nivel" type="nivel" not-null="true" update="false" access="field" />
        <property name="nome" column="nome" type="nome" not-null="true" update="false" access="field" />
        <many-to-one name="curriculo" class="br.com.working.entity.Curriculo" column="curriculo" />
    </class>
</hibernate-mapping>
 
classes Java:
 
public class Curriculo implements Serializable{
 
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
     
    private Integer id;
    private String objetivo;
    private Pessoa pessoa;
    private List<ExperienciaProfissional> ep;
    private List<FormacaoAcademica> fa;
    private List<Idioma> idioma;
 
    // getters and setters equals and hashcode
}
 
public class Idioma implements Serializable{
 
    /**
     * 
     */
    private static final long serialVersionUID = 4942411828844125491L;
 
    /* member variables */
    private Integer id;
    private Curriculo curriculo;
    private Nome nome;
    private Nivel nivel;
 
    // getters and setters equals and hashcode
}
 
arquivos enum:
 
public enum Nivel {
    NENHUM(0), BASICO(1), INTERMEDIARIO(2), AVANCADO(3), FLUENTE(4);
     
    private Integer nivel;
     
    /* constructor */
    Nivel (Integer nivel) {
        this.nivel = nivel;
    }
 
    /* getters and setters */
    public Integer getNivel() {
        return nivel;
    }
}
 
public enum Nome {
    INGLES("Inglês"), 
    ESPANHOL("Espanhol");
     
     
    private String nome;
     
    /* constructor */
    Nome (String nome) {
        this.nome = nome;
    }
 
    /* getters and setters */
    public String getNome() {
        return nome;
    }
}
 
quando eu salvo o curriculo td dá certo eis o código:
 
    public static void main(String[] args) {     
 
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
         
        Pessoa p = new Pessoa();
        Curriculo curriculo = new Curriculo();
        Idioma idioma1 = new Idioma();
        Idioma idioma2 = new Idioma();
        Idioma idioma3 = new Idioma();
        List<Idioma> listIdioma = new ArrayList<Idioma>();
 
        p.setDtNascimento(new GregorianCalendar().getTime());
        p.setEstCivil("S");
        p.setNome("fabianoooooooooooooooooooooooooooooooooooooooooo");
        p.setSexo("M");
        p.setLocalNascimento("campinas");
        p.setCurriculo(curriculo);
 
        idioma1.setNivel(Nivel.AVANCADO);
        idioma1.setNome(Nome.INGLES);
        idioma1.setCurriculo(curriculo);
         
        idioma2.setNivel(Nivel.NENHUM);
        idioma2.setNome(Nome. ESPANHOL);
        idioma2.setCurriculo(curriculo);
         
        idioma3.setNivel(Nivel.FLUENTE);
        idioma3.setNome(Nome.INGLES);
        idioma3.setCurriculo(curriculo);
         
        listIdioma.add(idioma1);
        listIdioma.add(idioma2);
        listIdioma.add(idioma3);
         
        curriculo.setIdioma(listIdioma);
        curriculo.setObjetivo("teste");         
        curriculo.setPessoa(p);
         
        session.save(p);
         
        tx.commit();
        session.flush();
        session.close();
}
 
até aqui td funciona.. tô salvando os arquivos.. agora vou alterar e é onde dá o erro.
eis o código:
 
    public static void main(String[] args) {     
 
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
         
        PessoaDAO pDao = new PessoaDAO();
        CurriculoDAO cDao = new CurriculoDAO();
         
        Pessoa p = pDao.getPessoa(444);
        Curriculo curriculo = cDao.getCurriculo(444);
        Idioma idioma1 = new Idioma();
        Idioma idioma2 = new Idioma();
        Idioma idioma3 = new Idioma();
        List<Idioma> listIdioma = new ArrayList<Idioma>();
 
        p.setDtNascimento(new GregorianCalendar().getTime());
        p.setEstCivil("S");
        p.setNome("fabianoooooooooooooooooooooooooooooooooooooooooo");
        p.setSexo("M");
        p.setLocalNascimento("campinas");
        p.setCurriculo(curriculo);
 
        idioma1.setNivel(Nivel.AVANCADO);
        idioma1.setNome(Nome.INGLES);
        idioma1.setCurriculo(curriculo);
         
        idioma2.setNivel(Nivel.NENHUM);
        idioma2.setNome(Nome. ESPANHOL);
        idioma2.setCurriculo(curriculo);
         
        idioma3.setNivel(Nivel.FLUENTE);
        idioma3.setNome(Nome.INGLES);
        idioma3.setCurriculo(curriculo);
         
        listIdioma.add(idioma1);
        listIdioma.add(idioma2);
        listIdioma.add(idioma3);
         
        curriculo.setIdioma(listIdioma);
        curriculo.setObjetivo("teste");         
        curriculo.setPessoa(p);
         
        session.merge(p);
         
        tx.commit();
        session.flush();
        session.close();
}
 
eis o erro:
 
Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.working.entity.Idioma.nivel
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:95)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:238)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:170)
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:714)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:696)
    at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:268)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:291)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:239)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:319)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:265)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:242)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:153)
    at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:459)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:167)
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:714)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:696)
    at org.hibernate.engine.CascadingAction$6.cascade(CascadingAction.java:268)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:291)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:239)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:192)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:153)
    at org.hibernate.event.def.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:459)
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:318)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:167)
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:81)
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:704)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:688)
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:692)
    at br.com.working.test.Teste.main(Teste.java:77)
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Opa !

Para alterar voce nao pode criar uma lista nova de idiomas e setar... para alterar voce deve RECUPERAR a lista que Já está salva e alterar os itens dentro dela...

TEste e me avise !

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

fiz a alteração que vc pediu.. agora não dá mais erro .. porêm, nenhuma alteração é feita.
algo ainda está errado taí o código:
 
    public static void main(String[] args) {     
     
 
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
         
        PessoaDAO pDao = new PessoaDAO();
        CurriculoDAO cDao = new CurriculoDAO();
         
        Pessoa p = pDao.getPessoa(444);
        Curriculo curriculo = cDao.getCurriculo(444);
        List<Idioma> listIdioma = cDao.getIdioma(curriculo.getId());
         
        p.setDtNascimento(new GregorianCalendar().getTime());
        p.setEstCivil("S");
        p.setNome("fabianoooooooooooooooooooooooooooooooooooooooooo");
        p.setSexo("M");
        p.setLocalNascimento("campinas");
        p.setCurriculo(curriculo);
 
        listIdioma.get(0).setNivel(Nivel.FLUENTE);
        listIdioma.get(0).setNome(Nome.INGLES);
        listIdioma.get(0).setCurriculo(curriculo);
         
        listIdioma.get(1).setNivel(Nivel.FLUENTE);
        listIdioma.get(1).setNome(Nome. ESPANHOL);
        listIdioma.get(1).setCurriculo(curriculo);
         
        listIdioma.get(2).setNivel(Nivel.FLUENTE);
        listIdioma.get(2).setNome(Nome.INGLES);
        listIdioma.get(2).setCurriculo(curriculo);
         
        curriculo.setIdioma(listIdioma);
        curriculo.setObjetivo("teste");         
        curriculo.setPessoa(p);
         
        session.merge(p);
         
        tx.commit();
        session.flush();
        session.close();
    }
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Esses seus DAOS estão criando sessions dentro ?

Crie um construtor nestes daos e passe o session que vc instancia por primeiro para eles utilizarem , teste e me fale.

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

Não estou usando mais os daos.. e ainda não está salvando..

    public static void main(String[] args) {         
 
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = session.beginTransaction();
         
        Pessoa p = (Pessoa) session.get(Pessoa.class, 444);
        Curriculo curriculo = (Curriculo) session.get(Curriculo.class, p.getId());         
        List<Idioma> listIdioma = curriculo.getIdioma();
         
        p.setDtNascimento(new GregorianCalendar().getTime());
        p.setEstCivil("S");
        p.setNome("fabianoooooooooooooooooooooooooooooooooooooooooo");
        p.setSexo("M");
        p.setLocalNascimento("campinas");
        p.setCurriculo(curriculo);
 
        listIdioma.get(0).setNivel(Nivel.FLUENTE);
        listIdioma.get(0).setNome(Nome.INGLES);
        listIdioma.get(0).setCurriculo(curriculo);
         
        listIdioma.get(1).setNivel(Nivel.FLUENTE);
        listIdioma.get(1).setNome(Nome. ESPANHOL);
        listIdioma.get(1).setCurriculo(curriculo);
         
        listIdioma.get(2).setNivel(Nivel.FLUENTE);
        listIdioma.get(2).setNome(Nome.INGLES);
        listIdioma.get(2).setCurriculo(curriculo);
         
        curriculo.setIdioma(listIdioma);
        curriculo.setObjetivo("teste");         
        curriculo.setPessoa(p);
         
        session.merge(p);
         
        tx.commit();
        session.flush();
        session.close();
    }
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Faz um teste por favor:

Antes de fechar a sessao coloque:


session.update(listIdioma.get(0));
session.update(listIdioma.get(1));
session.update(listIdioma.get(2));
GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

fiz mais esse teste a não funciona.. apenas as tabelas pessoa e curriculo são alteradas.. nada acontece na tabela Idioma (onde estão os campos enums)....

eu criei uma app para testar esse problema se vc concordar posso te mandar por email.. se vc tiver o oracle instalado vai levar 5 min. pra instalar... tem os comandos para criar as 3 tabelas e a classe de teste... só vai precisar alterar o arquivo config do hibernate...
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Mande por favor...

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

já mandei.. valeu
GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

encontrou alguma coisa?
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Opa !


Eu nao recebi , poderia tentar denovo ?

Mande tmb para dyego.leal@gmail.com !!!!

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

acabei de mandar..

Obrigado!
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Recebi e estou vendo aqui...

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

Valeu..

tô na espera...
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Olha , eu botei a ultima versao do hibernate e funcionou aqui !

Tente atualizar !

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

era estranho não funcionar mesmo...

Valeu mesmo muito obrigado!!

td de bom!!!

Fabiano
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Opa !
Resolvido ?

ValeuZ !
GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

eu atualizei as libs do hibernate no projeto e deu problema na configuração...

vc pode passar o link de onde vc pegou as libs do hibernate que funciona?

valeu!
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

direto no www.hibernate.org

poderia colar o erro aqui ?

GOSTEI 0
Fabiano Souza

Fabiano Souza

17/08/2010

baixei este arquivo do site do hibernate.org hibernate-distribution-

3.6.0.CR2

e adicionei as seguintes libs no meu projeto:

antlr-2.7.6.jar
c3p0-0.9.1.jar
cglib-2.2.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate3.jar
javassist-3.12.0.GA.jar
jta-1.1.jar
ojdbc14.jar
slf4j-api-1.6.1.jar

quando eu rodo a aplicação dá esse erro:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for

further details.
Exception in thread "main" java.lang.ExceptionInInitializerError
    at br.com.working.util.HibernateUtil.<clinit>

(HibernateUtil.java:14)
    at br.com.working.test.Teste.main(Teste.java:22)
Caused by: java.lang.NoClassDefFoundError:

javax/persistence/EntityListeners
    at

org.hibernate.cfg.annotations.reflection.JPAMetadataProvider.getDefault

s(JPAMetadataProvider.java:96)
    at

org.hibernate.annotations.common.reflection.java.JavaReflectionManager.

getDefaults(JavaReflectionManager.java:226)
    at org.hibernate.cfg.Configuration.secondPassCompile

(Configuration.java:1353)
    at org.hibernate.cfg.Configuration.buildSessionFactory

(Configuration.java:1824)
    at br.com.working.util.HibernateUtil.<clinit>

(HibernateUtil.java:12)
    ... 1 more
Caused by: java.lang.ClassNotFoundException:

javax.persistence.EntityListeners
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    ... 6 more
GOSTEI 0
Dyego Carmo

Dyego Carmo

17/08/2010

Falta o arquivo de biblioteca sf4logj.jar

Coloque ele no classpath e tente denovo !

GOSTEI 0
POSTAR