Hibernate + Chave composta

144 views
Skip to first unread message

Alcelyo Roberto

unread,
Aug 22, 2007, 10:44:21 AM8/22/07
to pb...@googlegroups.com, DFJug - Brasilia Java Users Group, raph...@j2eebrasil.com.br
Boa tarde, ainda não conseguir resolver um problema com chave composta, um do tipo primitivo e outro um objeto. O mapeamento está sendo feito assim:

@Embeddable
public class GcTepPk implements Serializable{    
     private GcTet tep_tetcod;
     private float tep_preco;
....... get e set

@Entity
@Table(name="GCTEP")
@IdClass(GcTepPk.class)
public class GcTep {
     
    private int tep_qtdmin;
    private boolean deleted;
    @Id
    private float tep_preco;
    @Id
    @ManyToOne(fetch=FetchType.LAZY)
    private GcTet tep_tetcod;
        get e set

Quando  rodo mostra esse erro:

INFO: Binding entity from annotated class: br.com.teste.beans.GcTet
22/08/2007 11:29:48 org.hibernate.cfg.annotations.EntityBinder bindTable
INFO: Bind entity br.com.teste.beans.GcTet on table GCTET
org.hibernate.AnnotationException : mappedBy reference an unknown target entity property: br.com.teste.beans.GcTep.tep_tetcod in br.com.teste.beans.GcTet.gcTeps
        at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java :506)
        at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:471)
        at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43)
        at org.hibernate.cfg.Configuration.secondPassCompile (Configuration.java:1054)
        at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:296)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1210)
        at br.com.teste.dao.HibernateUtil.getSession(HibernateUtil.java:29)
        at br.com.teste.dao.DaoImplementado.salvarOuAlterar(DaoImplementado.java:29)
        at br.com.teste.main.Main.main(Main.java:60)
Exception in thread "main" java.lang.NullPointerException
        at br.com.teste.dao.HibernateUtil.getSession(HibernateUtil.java:35)
        at br.com.teste.dao.DaoImplementado.salvarOuAlterar(DaoImplementado.java :29)
        at br.com.teste.main.Main.main(Main.java:60)
Java Result: 1


OBS: Quando faço o mapeamento com os dois atributos primitivos funciona ok, só acontece quando coloco chave com um dos atributos sendo um objeto.

Valeu

 
--
Alcelyo R Mariz
Bacharel em Sistemas de Informação

Jorge Fernando

unread,
Aug 22, 2007, 11:15:39 AM8/22/07
to pb...@googlegroups.com
De acordo com o livro Hibernate in Action esse é um mapeamento que pode resolver o seu problema. Particularmente nunca utilizei essa estratégia com hibernate, mas o autor chama a atenção para que os métodos equals() e hashcode() sejam implementados.

Existem mais informações sobre isso na parte 8.3.1 do livro Hibernate in Action

<class name="User" table="USER">
<composite-id>
<key-property name="username"
column="USERNAME"/>
<key-property name="organizationId"
column="ORGANIZATION_ID"/>
</composite-id>
<version name="version"
column="VERSION"
unsaved-value="0"/>
...
</class
--
"Que homem é aquele que não pode fazer do mundo um lugar melhor"
fone:(83)88087401
email: jorge...@yahoo.com.br
          jorgefe...@gmail.com
messenger:theufo...@hotmail.com

Jorge Fernando

unread,
Aug 22, 2007, 11:17:29 AM8/22/07
to pb...@googlegroups.com
Ops, esqueci de explicar o mapeamento. ele foi retirado do livro Hibernate in Action e é sobre uma classe chamada User, que tem a chave primária composta por dois atributos username e organizationId.

Alcelyo Roberto

unread,
Aug 22, 2007, 4:07:59 PM8/22/07
to pb...@googlegroups.com
Desculpa por não ter falado mas estou usando anotações. Alguem já passou por este problema ? É possível fazer este tipo de chave composta com o hibernate  usando anotacoes ? Valeu

Jorge Fernando

unread,
Aug 22, 2007, 5:04:48 PM8/22/07
to pb...@googlegroups.com

Jorge Fernando

unread,
Aug 22, 2007, 5:06:40 PM8/22/07
to pb...@googlegroups.com

dmcabral

unread,
Sep 27, 2007, 11:18:10 AM9/27/07
to PBJug
Estou com o mesmo problema e, mesmo lendo os links, não consegui
resolver.

On 22 ago, 18:06, "Jorge Fernando" <jorgefernand...@gmail.com> wrote:
> Vê esse aki tbhttp://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/...


>
> On 8/22/07, Jorge Fernando <jorgefernand...@gmail.com> wrote:
>
>
>
>
>
> > Dá uma olhada nisso
> >http://javawora.blogspot.com/2007/08/hibernate-composite-id.html
> > e tb nisso
> >http://www.hibernate.org/329.html
> > talvez tenha a resposta :)
>

> > On 8/22/07, Alcelyo Roberto <alce...@gmail.com > wrote:
>
> > > Desculpa por não ter falado mas estou usando anotações. Alguem já passou
> > > por este problema ? É possível fazer este tipo de chave composta com o
> > > hibernate usando anotacoes ? Valeu
>

> > > On 8/22/07, Jorge Fernando <jorgefernand...@gmail.com> wrote:
>
> > > > Ops, esqueci de explicar o mapeamento. ele foi retirado do livro
> > > > Hibernate in Action e é sobre uma classe chamada User, que tem a chave
> > > > primária composta por dois atributos username e organizationId.
>

> > > > On 8/22/07, Jorge Fernando <jorgefernand...@gmail.com> wrote:
>
> > > > > De acordo com o livro Hibernate in Action esse é um mapeamento que
> > > > > pode resolver o seu problema. Particularmente nunca utilizei essa estratégia
> > > > > com hibernate, mas o autor chama a atenção para que os métodos equals() e
> > > > > hashcode() sejam implementados.
>
> > > > > Existem mais informações sobre isso na parte 8.3.1 do livro
> > > > > Hibernate in Action
>
> > > > > <class name="User" table="USER">
> > > > > <composite-id>
> > > > > <key-property name="username"
> > > > > column="USERNAME"/>
> > > > > <key-property name="organizationId"
> > > > > column="ORGANIZATION_ID"/>
> > > > > </composite-id>
> > > > > <version name="version"
> > > > > column="VERSION"
> > > > > unsaved-value="0"/>
> > > > > ...
> > > > > </class
>

> > > > > email: jorge_fe...@yahoo.com.br
> > > > > jorgefernand...@gmail.com
> > > > > messenger:theufohun...@hotmail.com


>
> > > > --
> > > > "Que homem é aquele que não pode fazer do mundo um lugar melhor"
> > > > fone:(83)88087401

> > > > email: jorge_fe...@yahoo.com.br
> > > > jorgefernand...@gmail.com
> > > > messenger:theufohun...@hotmail.com


>
> > > --
> > > Alcelyo R Mariz
> > > Bacharel em Sistemas de Informação
>
> > --
> > "Que homem é aquele que não pode fazer do mundo um lugar melhor"
> > fone:(83)88087401

> > email: jorge_fe...@yahoo.com.br
> > jorgefernand...@gmail.com
> > messenger:theufohun...@hotmail.com


>
> --
> "Que homem é aquele que não pode fazer do mundo um lugar melhor"
> fone:(83)88087401

> email: jorge_fe...@yahoo.com.br
> jorgefernand...@gmail.com
> messenger:theufohun...@hotmail.com

Maurício Linhares

unread,
Sep 27, 2007, 2:58:47 PM9/27/07
to PBJug
Qual é a exceção?

Davi Cabral

unread,
Sep 28, 2007, 7:06:10 AM9/28/07
to pb...@googlegroups.com
Olá Maurício,

Irei fazer melhor, vou resumir o que fiz. Estou precisando criar uma classe com chave primária composta, em que uma das chaves componentes é um objeto e as demais são do tipo inteiro. Se eu alterar a chave componente do tipo complexo para o tipo primitivo, as coisas funcionam bem.

As descrições das tabelas que estou utilizando são

CREATE TABLE TB_PROC_SEQ (
NU_PROCESSO NUMBER(5)    ,                     
NU_ANO      NUMBER(4)           ,              
NU_VARA     NUMBER(3)           ,              
SQ_PROCESSO NUMBER(2)      ,                   
NU_TRIBUNAL NUMBER(2)          ,               
NU_DIGITO   NUMBER(1)             ,
PRIMARY KEY (NU_PROCESSO, NU_ANO, NU_VARA, SQ_PROCESSO)
)

CREATE TABLE TB_PROC_CLA (
NU_PROCESSO     NUMBER(5) , 
NU_ANO          NUMBER(4)                             ,
NU_VARA         NUMBER(3)                             ,
SQ_CLASSE       NUMBER(2)                            ,
SQ_PROCESSO     NUMBER(2),
CD_CLASSE       NUMBER(3)                     ,
PRIMARY KEY (NU_PROCESSO, NU_ANO, NU_VARA, SQ_CLASSE, SQ_PROCESSO)
)             


CREATE TABLE TB_CLASSE(
CD_CLASSE       NUMBER(3) PRIMARY KEY,                           
TP_CLASSE       VARCHAR2(1)                     ,     
NM_CLASSE       VARCHAR2(6)                       ,   
DS_CLASSE       VARCHAR2(40)                      
)

CREATE TB_VARA(
NU_VARA         NUMBER(3)   PRIMARY KEY   ,
SQ_VARA         NUMBER(3)                              ,
NM_VARA         VARCHAR2(40)
)

------------------------------------------------------------------------------------------------------------------------------------------------------

As classes que estou tentando criar são as que seguem abaixo e aquela que possui uma chave primária composta é a classe Processo, sendo a chave componente do tipo Vara.

--------------------------------------------------------------------------------------------------------------------------------------------------


import ...

@Entity
@Table(name = "tb_proc_seq")
@IdClass(Processo.ProcessoId.class)
public class Processo {



    private static NumberFormat nf2 = new DecimalFormat("00");
    private static NumberFormat nf3 = new DecimalFormat("000");
    private static NumberFormat nf5 = new DecimalFormat("00000");

    public Processo() {

    }

    @Id
    private int numero;
    @Id
    private int ano;
    // @Id
    // private int vara;
    @Id
    private int sequencial;
    //@EmbeddedId
    @ManyToOne(optional=false)
    @PrimaryKeyJoinColumn(name = "nu_vara", referencedColumnName = "nu_vara")
    private Vara vara;

    @Column(name = "nu_digito")
    private int digito;

    public void setVara(Vara vara) {
        this.vara = vara;
    }

    public Vara getVara() {
        return vara;
    }


    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @OrderBy
    @JoinTable(name = "TB_PROC_CLA", joinColumns = {
            @JoinColumn(name = "NU_PROCESSO", referencedColumnName = "NU_PROCESSO"),
            @JoinColumn(name = "NU_ANO", referencedColumnName = "NU_ANO"),
            @JoinColumn(name = "NU_VARA", referencedColumnName = "NU_VARA"),
            @JoinColumn(name = "SQ_PROCESSO", referencedColumnName = "SQ_PROCESSO") }, inverseJoinColumns = @JoinColumn(name = "CD_CLASSE", referencedColumnName = "CD_CLASSE"))
    private Collection<Classe> classes;

    public void setClasses(Collection<Classe> classes) {
        this.classes = classes;
    }

    public Collection<Classe> getClasses() {
        return classes;
    }

    public void setNumero(int numero) {
        this.numero = numero;
    }

    public int getNumero() {
        return numero;
    }

    public void setAno(int ano) {
        this.ano = ano;
    }

    public int getAno() {
        return ano;
    }



    public void setSequencial(int sequencial) {
        this.sequencial = sequencial;
    }

    public int getSequencial() {
        return sequencial;
    }

    public String toString() {
        return nf5.format(getNumero()) + "." + getAno() + "."
                + nf3.format (getVara()) + ".13." + nf2.format(getSequencial())
                + "-" + getDigito();
    }

    public static class ProcessoId implements Serializable {
        @Column(name = "nu_processo", nullable = false)
        private int numero;
        @Column(name = "nu_ano", nullable = false)
        private int ano;
        @Column(name = "nu_vara", nullable = false)
        private int vara;
        // @Column(name = "nu_vara")

        //private Vara vara;
        @Column(name = "sq_processo", nullable = false)
        private int sequencial;

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (int) (ano ^ (ano >>> 32));
            result = prime * result + (int) (numero ^ (numero >>> 32));
            result = prime * result + (int) (sequencial ^ (sequencial >>> 32));
            result = prime * result
                    + (int) (vara ^ (vara >>> 32));
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            final ProcessoId other = (ProcessoId) obj;
            if (ano != other.ano)
                return false;
            if (numero != other.numero)
                return false;
            if (sequencial != other.sequencial)
                return false;
            if (vara != other.vara)
                return false;
            return true;
        }

    }

    public void setDigito(int digito) {
        this.digito = digito;
    }

    public int getDigito() {
        return digito;
    }
//
//     public void setVara(int vara) {
//     this.vara = vara;
//     }
//   
//     public int getVara() {
//     return vara;
//     }

}

-----------------------------------------------------------------------------------------------------------------------

import ...


@Entity
@Table(name = "TB_VARA")
public class Vara {   
    @Id   
    @Column(name = "nu_vara", nullable = false)
    private int codigo;
    @Column(name = "nm_vara", nullable = false)   
    private String descricao;
   
    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }
    public int getCodigo() {
        return codigo;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    public String getDescricao() {
        return descricao;
    }   
    public String toString(){
        return getDescricao()+" ("+getCodigo()+")";
    }
}
-----------------------------------------------------------------------------------------------------------------
import ....

@Entity
@Table(name = "TB_CLASSE")


public class Classe {
    @Column(name = "cd_classe", nullable = false)
    @Id
    private int codigo;
    @Column(name = "nm_classe", nullable = false)
    private String abreviacao;
    @Column(name = "ds_classe", nullable = false)
    private String descricao;


    public void setCodigo(int codigo) {
        this.codigo = codigo;
    }

    public int getCodigo() {
        return codigo;
    }

    public void setAbreviacao(String abreviacao) {
        this.abreviacao = abreviacao;
    }

    public String getAbreviacao() {
        return abreviacao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    public String getDescricao() {
        return descricao;
    }
    public String toString(){
        return descricao+" ("+abreviacao+")";
    }

}
-----------------------------------------------------------------------------------------------------------------
A classe de teste é a seguinte

import ....

public class ProcessoTest {

    private EntityManagerFactory emf;
    private EntityManager em;

    @Before
    public void initEmfAndEm() {
        // BasicConfigurator.configure();
        Logger.getLogger("org").setLevel(Level.ERROR);

        emf = Persistence
                .createEntityManagerFactory("jurisprudenciaPersistenceUnit");
        em = emf.createEntityManager();

    }

    @After
    public void cleanup() {
        em.close();
    }

    @SuppressWarnings("unchecked")
    @Test
    public void insertAndRetrieve() {
        int numero = 505, ano = 1996, vara = 10, sequencial = 0;
        em.getTransaction().begin();
        Processo proc;
        Vara v = new Vara();
        v.setCodigo(vara);
        List<Processo> list = em.createQuery(
                "select DISTINCT p from Processo p" + " where p.numero = "
                        + numero + " and p.ano=" + ano
                        // + " and p.vara =" + vara
                        + " and p.sequencial= " + sequencial
                        // +" and c.abreviacao = 'RT'"
                        //+ " and p.vara.codigo = " + vara
                        ).getResultList();

        assertEquals(1, list.size());
        proc = list.get(0);
        assertEquals(numero, proc.getNumero());
        assertEquals(ano, proc.getAno ());
        // assertEquals(vara, proc.getVara());
        assertEquals(sequencial, proc.getSequencial());

    }

}
---------------------------------------------------------------------------------------------------------
O erro que estou obtendo com o código do jeito que está é

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of entity.Processo.vara
    at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:630)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:75)
    at entity.ProcessoTest.insertAndRetrieve(ProcessoTest.java:55)
....
Caused by: org.hibernate.PropertyAccessException: could not set a field value by reflection setter of entity.Processo.vara
    at org.hibernate.property.DirectPropertyAccessor$DirectSetter.set(DirectPropertyAccessor.java:91)
    at org.hibernate.tuple.component.AbstractComponentTuplizer.setPropertyValues(AbstractComponentTuplizer.java:81)
    at     ... 40 more


Já tentei colocar o campo vara da classe ProcessoId como sendo do tipo complexo Vara, mas também não funcionou. Além disso, fiz outras tentativas as quais deixei comentadas dentro do próprio código.




Tel: (83) 3533-6059/8801-9872

Davi Cabral

unread,
Sep 28, 2007, 12:59:41 PM9/28/07
to pb...@googlegroups.com
Olá Maurício,

Encontrei a solução. A questão era que eu deveria ter colocado o mapeamento na classe ProcessoId em vez da classe Processo. Segue abaixo as classes com o problema solucionado

@Entity
@Table(name = "tb_proc_seq")
@IdClass(Processo.ProcessoId.class)
public class Processo {

    private static NumberFormat nf2 = new DecimalFormat("00");
    private static NumberFormat nf3 = new DecimalFormat("000");
    private static NumberFormat nf5 = new DecimalFormat("00000");

    public Processo() {

    }

    @Id
    private Integer numero;
    @Id
    private Integer ano;
    @Id
    private Integer sequencial;
    @Id

    private Vara vara;

    @Column(name = "nu_digito")
    private Integer digito;


    public void setVara(Vara vara) {
        this.vara = vara;
    }

    public Vara getVara() {
        return vara;
    }

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @OrderBy
    @JoinTable(name = "TB_PROC_CLA", joinColumns = {
            @JoinColumn(name = "NU_PROCESSO", referencedColumnName = "NU_PROCESSO"),
            @JoinColumn(name = "NU_ANO", referencedColumnName = "NU_ANO"),
            @JoinColumn(name = "NU_VARA", referencedColumnName = "NU_VARA"),
            @JoinColumn(name = "SQ_PROCESSO", referencedColumnName = "SQ_PROCESSO") }, inverseJoinColumns = @JoinColumn(name = "CD_CLASSE", referencedColumnName = "CD_CLASSE"))
    private Collection<Classe> classes;

    public void setClasses(Collection<Classe> classes) {
        this.classes = classes;
    }

    public Collection<Classe> getClasses() {
        return classes;
    }

    public void setNumero(Integer numero) {
        this.numero = numero;
    }

    public Integer getNumero() {
        return numero;
    }

    public void setAno(Integer ano) {
        this.ano = ano;
    }

    public Integer getAno() {
        return ano;
    }

    public void setSequencial(Integer sequencial) {
        this.sequencial = sequencial;
    }

    public Integer getSequencial() {

        return sequencial;
    }

    public String toString() {
        return nf5.format(getNumero()) + "." + getAno() + "."
                + nf3.format (getVara().getCodigo()) + ".13." + nf2.format(getSequencial())

                + "-" + getDigito();
    }

    public static class ProcessoId implements Serializable {
        @Column(name = "nu_processo", nullable = false)
        private Integer numero;

        @Column(name = "nu_ano", nullable = false)
        private Integer ano;
        @ManyToOne(cascade = { CascadeType.REFRESH,
                CascadeType.MERGE , CascadeType.PERSIST }, optional = false)
        @JoinColumn(name = "nu_vara", referencedColumnName = "nu_vara")
        private Vara vara;
        @Column(name = "sq_processo", nullable = false)
        private Integer sequencial;

    }

    public void setDigito(Integer digito) {
        this.digito = digito;
    }

    public Integer getDigito() {
        return digito;
    }

}
-----------------------------------------------------------------------------------------------

@Entity
@Table(name = "TB_VARA")
public class Vara implements Serializable{   
    @Id   
    @Column(name = "nu_vara", nullable = false)
    private Integer codigo;

    @Column(name = "nm_vara", nullable = false)   
    private String descricao;
   
    public void setCodigo(Integer codigo) {
        this.codigo = codigo;
    }
    public Integer getCodigo() {

        return codigo;
    }
    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }
    public String getDescricao() {
        return descricao;
    }   
    public String toString(){
        return getDescricao()+" ("+getCodigo()+")";
    }


}
-------------------------------------------------------------------------------------------
@Entity
@Table(name = "TB_CLASSE")
public class Classe {
    @Column(name = "cd_classe", nullable = false)
    @Id
    private Integer codigo;
    @Column(name = "nm_classe", nullable = false)
    private String abreviacao;
    @Column(name = "ds_classe", nullable = false)
    private String descricao;


    public void setCodigo(Integer codigo) {
        this.codigo = codigo;
    }

    public Integer getCodigo() {
Analista Judiciário, TRT 13a Região
Tel: (83) 3533-6059/8801-9872



--
Davi Medeiros Cabral
Mestre em Eng. Software, UFPE
Graduando em Direito, UFPB
Analista Judiciário, TRT 13a Região
Tel: (83) 3533-6059/8801-9872


--
Davi Medeiros Cabral
Mestre em Eng. Software, UFPE
Graduando em Direito, UFPB
Analista Judiciário, TRT 13a Região
Tel: (83) 3533-6059/8801-9872
Reply all
Reply to author
Forward
0 new messages