Insert , delete e update em entity com java composta

9 respostas
L

Boa tarde amigos,

Estou com um problema e acho que vocês saberão me ajudar com facilidade. Eu tenho um entity que possui uma chave composta. Para efetuar esse mapeamento tenho as seguintes classes:

1 - asSistemaModuloPK

import java.io.Serializable;
import java.math.BigInteger;
import javax.persistence.Embeddable;

@Embeddable
public class asSistemaModuloPK implements Serializable {

    private String sistema;
    private BigInteger modulo;
    
    public asSistemaModuloPK() {
    }  
    
    public asSistemaModuloPK(String sistema, BigInteger modulo) {  
        this.sistema = sistema;
        this.modulo  = modulo;
    }      
    
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (sistema != null ? sistema.hashCode() : 0);
        hash += (modulo != null ? modulo.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof asSistemaModuloPK)) {
            return false;
        }
        asSistemaModuloPK other = (asSistemaModuloPK) object;
        if ((this.sistema == null && other.sistema != null) ||
            (this.sistema != null && !this.sistema.equals(other.sistema))) {
            return false;
        }
        if ((this.modulo == null && other.modulo != null) ||
            (this.modulo != null && !this.modulo.equals(other.modulo))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "websis.model.as.asSistemaModuloPK[sistema=" + sistema + ", modulo=" + modulo + "]";
    }
    
    public BigInteger getModulo() {
        return modulo;
    }

    public void setModulo(BigInteger modulo) {
        this.modulo = modulo;
    }

    public String getSistema() {
        return sistema;
    }

    public void setSistema(String sistema) {
        this.sistema = sistema;
    }
}

2 - asSistemaModulo

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
  @Table(name = "assistema_modulo")
  @NamedQueries
  ({
    @NamedQuery(name = "asSistemaModulo.searchAll",     query = "select e from asSistemaModulo e"),
    @NamedQuery(name = "asSistemaModulo.searchFgAtivo", query = "select e from asSistemaModulo e where e.fgAtivo = :fgAtivo"),
    @NamedQuery(name = "asSistemaModulo.searchById",    query = "select e from asSistemaModulo e where e.asSistemaModuloPK.sistema = :sistema and e.asSistemaModuloPK.modulo = :modulo")
  })

public class asSistemaModulo implements Serializable {

    /* Campo de chave primária embutido */
    @EmbeddedId  
    private asSistemaModuloPK asSistemaModuloPK; 
    
    private static final long serialVersionUID = 1L;
    @GeneratedValue(strategy = GenerationType.AUTO)

    @Id
    @ManyToOne
    @JoinColumn(name="sistema", referencedColumnName="id_sistema", insertable = false, updatable = false)
    private asSistema sistema;

    @Id
    @ManyToOne   
    @JoinColumn(name="modulo", referencedColumnName="id_modulo", insertable = false, updatable = false)
    private asModulo modulo;

    @Column(name = "fg_ativo", nullable = false)
    private String fgAtivo;

    public asSistemaModulo() {
    }

    public asSistema getSistema() {
        return sistema;
    }

    public void setSistema(asSistema sistema) {
        this.sistema = sistema;
    }

    public asModulo getModulo() {
        return modulo;
    }

    public void setModulo(asModulo modulo) {
        this.modulo = modulo;
    }

    public String getFgAtivo() {
        return fgAtivo;
    }

    public void setFgAtivo(String fgAtivo) {
        this.fgAtivo = fgAtivo;
    }
}

As queries estão funcionando perfeitamente, porém estou com dificuldades de como fazer os inserts, updades e deletes. Alguém teria algum exemplo.
Estou tentando fazer da seguinte forma:

/* Grava o objeto no banco */
    public String save(asSistemaModulo asSistemaModuloPar) {
        try {

            /* Instancia objetos */
            em = getEntityManager();
            em.getTransaction().begin();
            em.persist(asSistemaModuloPar);
            em.getTransaction().commit();
            return "saveSucess";

        } catch (Exception ex) {
            ex.printStackTrace();
            return "saveError";
        } finally {
            em.close();

        }
    }

Porém mesmo com o asSistemaModuloPar preenchido ele diz que eu estou tentando inserir nulo nos campos chave. Onde estou errando ?Como deve ser o persist ?

Obrigado

9 Respostas

R

Não estaria aqui o problema?

#     @Id  
#     @ManyToOne  
#     @JoinColumn(name="sistema", referencedColumnName="id_sistema", insertable = false, updatable = false)  
#     private asSistema sistema;  
#   
#     @Id  
#     @ManyToOne     
#     @JoinColumn(name="modulo", referencedColumnName="id_modulo", insertable = false, updatable = false)  
#     private asModulo modulo;

Pelo que entendi, você quer um tipo asSistema e um asModulo, porém sua chave comp. é um Integer e uma String…

L

Boa noite,

Pelo que estou vendo, tem muita coisa errada nesse relacionamento.
Vou dar mais uma mexida aqui. Se alguém possuir algum exemplo parecido e puder postar eu agradeço.
Obrigado.

L

Galera, vou tentar melhorar o meu post. Vamos começar do começo rs.

BANCO DE DADOS:

table ASSISTEMA
id_sistema varchar CHAVE PRIMARIA
nome varchar

table ASMODULO
id_modulo number CHAVE PRIMARIA
nome varchar

table ASSISTEMA_MODULO
sistema varchar – REFERENCIA PARA ASSISTEMA E CHAVE PRIMARIA
modulo number – REFERENCIA PARA ASMODULO E CHAVE PRIMARIA
fg_ativo varchar

Pergunta. Como seria o mapeamento da entity asSistemaModulo entity’s ?
Alterei para o codigo abaixo:

import java.io.Serializable;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Embeddable
public class asSistemaModuloPK implements Serializable {

    
    @ManyToOne
    @JoinColumn(name="sistema", referencedColumnName="id_sistema", insertable = true, updatable = true)
    private asSistema sistema;
    
    @ManyToOne   
    @JoinColumn(name="modulo", referencedColumnName="id_modulo"  , insertable = true, updatable = true)
    private asModulo modulo;

    
    public asSistemaModuloPK() {
    }
    

    public asSistemaModuloPK(asSistema sistema, asModulo modulo) {  
        this.sistema = sistema;
        this.modulo  = modulo;
    }      
    
    @Override
    public int hashCode() {
        int hash = 0;
        hash += (getSistema() != null ? getSistema().hashCode() : 0);
        hash += (getModulo() != null ? getModulo().hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof asSistemaModuloPK)) {
            return false;
        }
        asSistemaModuloPK other = (asSistemaModuloPK) object;
        if ((this.getSistema() == null && other.getSistema() != null) ||
            (this.getSistema() != null && !this.sistema.equals(other.sistema))) {
            return false;
        }
        if ((this.getModulo() == null && other.getModulo() != null) ||
            (this.getModulo() != null && !this.modulo.equals(other.modulo))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "websis.model.as.asSistemaModuloPK[sistema=" + getSistema() + ", modulo=" + getModulo() + "]";
    }

    public asSistema getSistema() {
        return sistema;
    }

    public void setSistema(asSistema sistema) {
        this.sistema = sistema;
    }

    public asModulo getModulo() {
        return modulo;
    }

    public void setModulo(asModulo modulo) {
        this.modulo = modulo;
    }
    
    
}

E

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

@Entity
  @Table(name = "assistema_modulo")
  @NamedQueries
  ({
    @NamedQuery(name = "asSistemaModulo.searchAll",     query = "select e from asSistemaModulo e"),
    @NamedQuery(name = "asSistemaModulo.searchFgAtivo", query = "select e from asSistemaModulo e where e.fgAtivo = :fgAtivo"),
    @NamedQuery(name = "asSistemaModulo.searchById",    query = "select e from asSistemaModulo e where e.asSistemaModuloPK.sistema = :sistema and e.asSistemaModuloPK.modulo = :modulo")
  })

public class asSistemaModulo implements Serializable {

    /* Campo de chave primária embutido */
    @EmbeddedId  
    private asSistemaModuloPK asSistemaModuloPK; 

    @Column(name = "fg_ativo", nullable = false)
    private String fgAtivo;

    public asSistemaModulo() {
    }
   
    public String getFgAtivo() {
        return fgAtivo;
    }

    public void setFgAtivo(String fgAtivo) {
        this.fgAtivo = fgAtivo;
    }

    public asSistemaModuloPK getAsSistemaModuloPK() {
        return asSistemaModuloPK;
    }

    public void setAsSistemaModuloPK(asSistemaModuloPK asSistemaModuloPK) {
        this.asSistemaModuloPK = asSistemaModuloPK;
    }
}

Mas agora esta dando esse erro:

A verdade é que estou perdido.
SOCORROOOO !!!
rs
Abraços

R

Como o próprio erro diz, sua classe PK está sem nenhum campo, ou seja, as classes que você usa lá(asSistema e asModulo) não estão mapeadas pelo que eu pude perceber…

Cola o código delas aí…

E, sem querer ser chato, use naming conventions, faz um bem danado viu e não fica tão confuso…

EDIT: Ah outra coisa confusa é aquele relacionamento da PK, eu não entendi o que você quer fazer ali… :cry:

L


Como o próprio erro diz, sua classe PK está sem nenhum campo, ou seja, as classes que você usa lá(asSistema e asModulo) não estão mapeadas pelo que eu pude perceber…

R: Quais classes você gostaria de ver ? Não são essas que aí estão ? Andei procurando um exemplo de chave composta com foreign key e não encontrei.

R: Imagina !!! Só vou te achar chato se você não me ensinar a usar esse tal de naming conventions rsrsrs. Me explica como uso isso.

[b]

R: Certo, vamos tentar simplificar o problema: Imagine as seguintes tabelas

ASSISTEMA
ID_SISTEMA VARCHAR - PK
NOME VARCHAR

ASMODULO
ID_MODULO NUMBER - PK
NOME VARCHAR

ASSISTEMA_MODULO
SISTEMA VARCHAR - PK e FK
MODULO NUMBER - PK e FK
FG_ATIVO VARCHAR

Dúvida:

Considerando que a tabela ASSISTEMA_MODULO possui uma chave composta ( sistema e modulo ) e a chave também é foreign key, como seria o entity dessa tabela ?

Acho que dessa vez a dúvida ficou um pouco mais clara. Acredito que todo mundo que já desenvolveu algum sistema usando JPA passou por isso. Eu estou iniciando o meu primeiro sistema usando JPA e só agora encontrei esse problema. Já procurei em vários lugares e ainda não encontrei… geralmente a galera do Forum sempre tem uma solução.

Obrigado amigos.
Valew RaulCarlin.

[/b]

R

Vamos lá:

Primeiro, naming conventions… http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html , aí tem tudo…

Segundo, na sua PK:

# @Embeddable  
# public class asSistemaModuloPK implements Serializable {  
#   
#       
#     @ManyToOne  
#     @JoinColumn(name="sistema", referencedColumnName="id_sistema", insertable = true, updatable = true)  
#     private asSistema sistema;  
#       
#     @ManyToOne     
#     @JoinColumn(name="modulo", referencedColumnName="id_modulo"  , insertable = true, updatable = true)  
#     private asModulo modulo;

As chaves são uma classe asModulo e uma classe asSistema, correto? O que são essas classes?

Na verdade, sua chave composta ficaria assim, se fossemos pensar que ela é composta por um VARCHAR e um NUMBER:

# @Embeddable  
# public class asSistemaModuloPK implements Serializable {  
#   
#       
#     private String idSistema;  
#     private Integer idModulo;

Aí você declararia somente a classe que representa essa composição:

# public class asSistemaModulo implements Serializable {  
#   
#     /* Campo de chave primária embutido */  
#     @EmbeddedId    
#     private asSistemaModuloPK asSistemaModuloPK;

Pronto, resolveríamos o problema do id. Agora, para relacionar a Sistema e Modulo, ficaria assim, pois estaríamos dizendo que o relacionamento é feito utilizando a PK, e nessa classe é que teríamos acesso aos objetos trazidos com o relacionamento, e não na PK, como aparentemente você estava fazendo:

# public class asSistemaModulo implements Serializable {  
#   
#     /* Campo de chave primária embutido */  
#     @EmbeddedId    
#     private asSistemaModuloPK asSistemaModuloPK;
#     @Id private String idSistema;
#     @Id private Integer idModulo;
#     @ManyToOne @PrimaryKeyJoinColumn private asSistema sistema;
#     @ManyToOne @PrimaryKeyJoinColumn private asModulo modulo;

Eu não sou bom de didática, mas tentei… testa aí e dá uma lida aqui que tem tudo o que você precisa saber(utilizando Hibernate):

http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/#entity-mapping-association

EDIT: Vou postar como eu uso chave composta, é assim:

@Entity
@IdClass(RoutePk.class)
public class Route implements Serializable {
    @Id private Integer id;
    @Id private String station;
...
}
@Embeddable
public class RoutePk implements Serializable{
    private int id;
    private String station;
...
}

Eu acho melhor…

L

Olá,

Vou tentar fazer essas alterações hoje a noite e aí te dou um retorno. Obrigado pela atenção, acho que vai dar certo agora.

Ahh… obrigado pela dica do Naming Conventions.
Abraços

L

Boa noite amigos.
Acho que fiz todos os testes que podia fazer e nenhum teste deu certo. Vou postar aqui todos os meus scripts e o erro que está dando. Espero que alguém já tenha passado por isso e possa me ajudar.

BANCO DE DADOS:
ORACLE XE.

TABELA ASSISTEMA

create table ASSISTEMA
(
  ID_SISTEMA VARCHAR2(2)   not null,
  NOME           VARCHAR2(40) not null,
  FG_ATIVO    VARCHAR2(3)   not null
);

  alter table ASSISTEMA
  add constraint PKASSISTEMA primary key (ID_SISTEMA);

TABELA ASMODULO.

create table ASMODULO
(
  ID_MODULO NUMBER not null,
  DESCRICAO VARCHAR2(60) not null,
  FG_ATIVO  VARCHAR2(3) not null
);

alter table ASMODULO
  add constraint PKASMODULO primary key (ID_MODULO);

TABELA ASSISTEMA_MODULO.

create table ASSISTEMA_MODULO
(
  SISTEMA  VARCHAR2(2) not null,
  MODULO   NUMBER         not null,
  FG_ATIVO VARCHAR2(3) not null
);

alter table ASSISTEMA_MODULO
add constraint PKASSISTEMA_MODULO primary key (SISTEMA, MODULO);

alter table ASSISTEMA_MODULO
add constraint FKASSIST_MOD_ASMODULO foreign key (MODULO)
references ASMODULO (ID_MODULO);

alter table ASSISTEMA_MODULO
add constraint FKASSIST_MOD_ASSISTEMA foreign key (SISTEMA)
references ASSISTEMA (ID_SISTEMA);

AGORA IREI COLOCAR OS MEUS ENTITY’S.
ASSISTEMA

@Entity
@Table(name = "assistema")
  @NamedQueries({
  @NamedQuery(name="asSistema.searchAll",     query="select e from asSistema e "),
  @NamedQuery(name="asSistema.searchFgAtivo", query="select e from asSistema e where e.fgAtivo = :fgAtivo"),
  @NamedQuery(name="asSistema.searchById",    query="select e from asSistema e where e.idSistema = :idSistema")
})

public class asSistema implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)

    @Column(name = "id_sistema", nullable = false)
    private String idSistema;

    @Column(name = "nome", nullable = false)
    private String nome;

    @Column(name = "fg_ativo", nullable = false)
    private String fgAtivo;

    @OneToMany(mappedBy = "sistema")
    private List<asOperacao> operacaoList;

    @OneToMany( mappedBy="sistema" )   
    private List<asSistemaModulo> sistemaModuloList;

    public asSistema() {
    }
   
   // gets e sets

ASMODULO

@Entity
@Table(name = "asmodulo")

  @NamedQueries({
  @NamedQuery(name="asModulo.searchAll",     query="select e from asModulo e "),
  @NamedQuery(name="asModulo.searchFgAtivo", query="select e from asModulo e where e.fgAtivo = :fgAtivo"),
  @NamedQuery(name="asModulo.searchById",    query="select e from asModulo e where e.idModulo = :idModulo")
})

public class asModulo implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)

    @Column(name = "id_modulo", nullable = false)
    private int idModulo;

    @Column(name = "descricao", nullable = false)
    private String descricao;

    @Column(name = "fg_ativo", nullable = false)
    private String fgAtivo;
    
    @OneToMany( mappedBy="modulo" )   
    private List<asSistemaModulo> sistemaModuloList;

    public asModulo() {
    }

   // GETS e SETS

E POR FIM, E ONDE MINHAS DÚVIDA ESTÃO:
ASSISTEMA_MODULOPK

@Embeddable
public class asSistemaModuloPK implements Serializable {

    private String  sistema;   
    private Integer modulo;  
    
    public asSistemaModuloPK() {
    }

   // GETS  E SETS.

e ASSISTEMA_MODULO.

@Entity
  @Table(name = "assistema_modulo")
  @NamedQueries
  ({
    @NamedQuery(name = "asSistemaModulo.searchAll",     query = "select e from asSistemaModulo e"),
    @NamedQuery(name = "asSistemaModulo.searchFgAtivo", query = "select e from asSistemaModulo e where e.fgAtivo = :fgAtivo"),
    @NamedQuery(name = "asSistemaModulo.searchById",    query = "select e from asSistemaModulo e where e.asSistemaModuloPK.sistema = :sistema and e.asSistemaModuloPK.modulo = :modulo")
  })

public class asSistemaModulo implements Serializable {

    /* Campo de chave primária embutido */
    @EmbeddedId  
    private asSistemaModuloPK asSistemaModuloPK; 
    
    @ManyToOne
    @JoinColumn(name="sistema",insertable=false,updatable=false) 
    private asSistema sistema;

    @ManyToOne
    @JoinColumn(name="modulo",insertable=false,updatable=false)    
    private asModulo modulo;

    @Column(name = "fg_ativo", nullable = false)
    private String fgAtivo;

    public asSistemaModulo() {
    }

   // GETS  e SETS

Bom pessoal, até aqui está tudo funcionando perfeitamente bem. Não tenho problemas com esses mapeamentos. Agora tenho o DAO que vou postar
logo abaixo. No momento de salvar o objeto no banco ele diz que não pode inserir null nas colunas SISTEMA e MODULO ( Ou seja, a chave ). O que fazer ? Onde estou errando ?

DAO:

/* Grava o objeto no banco */
    public String save(asSistemaModulo asSistemaModuloPar) {
        try {

            /* Instancia objetos */
            em = getEntityManager();
            em.getTransaction().begin();
            em.persist(asSistemaModuloPar);
            em.getTransaction().commit();
            return "saveSucess";

        } catch (Exception ex) {
            ex.printStackTrace();
            return "saveError";
        } finally {
            em.close();

        }
    }

Erro emitido pelo oracle:

Acho que estou perto de solucionar o problema graças algumas dicas do pessoal do fórum. Mas ainda me falta alguns conceitos e por isso estou apanhando um pouco.

Aguardo mais alguma dica, enquanto isso vou procurando o problema. Se eu conseguir resolver irei posta-lo aqui.
Obrigado.

L

Tentei mudar o código abaixo de : b [/b]

@ManyToOne
    @JoinColumn(name="sistema",referencedColumnName="id_sistema",insertable=false,updatable=false) 
    private asSistema sistema;

    @ManyToOne
    @JoinColumn(name="modulo", referencedColumnName="id_modulo",insertable=false,updatable=false)    
    private asModulo modulo;

PARA…

@ManyToOne
    @JoinColumn(name="sistema",referencedColumnName="id_sistema",insertable=true,updatable=false) 
    private asSistema sistema;

    @ManyToOne
    @JoinColumn(name="modulo", referencedColumnName="id_modulo",insertable=true,updatable=false)    
    private asModulo modulo;

Mas aí o erro muda. Vejam.

Criado 29 de junho de 2008
Ultima resposta 1 de jul. de 2008
Respostas 9
Participantes 2