Insert , delete e update em entity com java composta

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

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…

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.

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

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:

[quote]
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… [/quote]

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]

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…

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

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.

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.