(JPA) Algum exemplo real (Chave-Composta)

20 respostas
gugaa_df

Alguém possui algum exemplo de JPA com chave composta?
Estou tendo vários problemas com isso.
gostaria de um exemplo de um CRUD com chave-composta, já pesquisei e nao achei…

20 Respostas

albama

Segue o exemplo :
Omiti os getters and setters.

@Entity
@Table(name="adm03_hierarquia")
public class Hierarquia implements Serializable {
	private static final long serialVersionUID = 1L;
	
	@Id
	private HierarquiaId id;
	
	@Column(name="hier_visualizacao",length=11,nullable=false)
	private String visualizacao;
	
	@Column(name="hier_sn_possui_inferior",length=1,nullable=false)
	private String possuiInferior;

Chave composta

@Embeddable
public class HierarquiaId implements Serializable {
	private static final long serialVersionUID = 1L;
	
	@Column(name="hier_id_local_referencia",nullable=false)
	private int idLocalReferencia;
	
	@Column(name="hier_id_estrutura",nullable=false)
	private int idEstrutura;

Este codigo está ligado a logica do sistema que estou desenvolvendo , mas se tiver dúvidas , coloque aí que eu o pessoal vai respondendo.

Marco Aurélio

gugaa_df

é pq nao tem lógica os erros que estão dando aqui.
Como você está fazendo para inserir os dados e para a busca?

albama

Para salvar eu uso assim:

manager.persist(hierarquia);

Porém o id tem que estar preenchido.

Lembre que a minha chave é de tipo primitivo, se sua chave for objeto , também precisará preecher antes de mandar persistir.

albama

Para pesquisar a chave composta:

hierarquia = manager.find(Hierarquia.class, id);

Marco Aurélio

gugaa_df

Você preencha dessa mesma forma?

Portador portador = new Portador();

PortadorPK pk = new PortadorPK();
	pk.setConvenio(998);
	pk.setPortador(19668);
	
	portador.setPk(pk);

manager.persist(portador);

??

albama

A chave é assim mesmo.

Porém nao estou vendo na sua classe portador atributos que nao sao chave composta.

Veja o meu codigo para salvar com mais informações

// cria o id
		HierarquiaId id = new HierarquiaId();
		id.setIdLocalReferencia(idLocalReferencia);
		id.setIdEstrutura(idEstrutura);
        id.setIdLocalSuperior(idLocalReferencia);

Instancia o objeto

Hierarquia hierarquia = new Hierarquia();

Informa o id para ser persistido

hierarquia = manager.find(Hierarquia.class, id);

Qualquer coisa coloque o erro para tentarmos identificar.

Marco Aurélio

gugaa_df

é pq eu omiti os outros atributos da Classe portador, coloquei apenas a chave compsota.
Não da nenhum erro, o problema é que o registro vai corrompido na tabela, ou as vezes grava e nao mostra o registro, eu passo um valor e chega um valor todo estranho…

gugaa_df

é pq eu omiti os outros atributos da Classe portador, coloquei apenas a chave compsota.
Não da nenhum erro, o problema é que o registro vai corrompido na tabela, ou as vezes grava e nao mostra o registro, eu passo um valor e chega um valor todo estranho…

albama

Verifique se a chave compostá é com tipo de dado primitivo.

Caso nao seja é preciso navegar até localizar o id da chave.

Exemplo

class Pessoa{
  @Id
  private id;
}

chave composta

class PessoaPK
   private LocalTrabalho local;
   private Cargo cargo.
}

Como prencher a chave

PessoaPK pk =new  PessoaPK();
pk.setLocalTrabalho.setId(1);
pk.setCargo.setId(32);

Veja este codigo pode conter alguns erros mas olhe o conceito , a navegação que usei para localizar os ids da chave composta.
É necessario localizar a chave.

Verifique se é isso.

Marco Aurélio

gugaa_df

é pq eu omiti os outros atributos da Classe portador, coloquei apenas a chave compsota.
Não da nenhum erro, o problema é que o registro vai corrompido na tabela, ou as vezes grava e nao mostra o registro, eu passo um valor e chega um valor todo estranho…

gugaa_df

E tem uma classe que nao grava uma coluna da chave composta

albama

Por favor coloque seu código aqui.

gugaa_df
public static Comercios populaComercios(){
		Comercios comercios = new Comercios();
		ComerciosPK pk = new ComerciosPK();
		pk.setConvenio(998); //TODO Verificar pq nao está gravando aqui direito.
		pk.setComercio(17896);
		comercios.setPk(pk);
		comercios.setCnpj("99999999999999");
		comercios.setRazaoSocial("GUSTAVO TESTE");
		comercios.setNomeFantasia("teste");
               return comercios;
}
@Embeddable
public class ComerciosPK implements Serializable {
	@Column(name="CONVENIO")
	private Integer convenio;

	@Column(name="COMERCIO")
	private long comercio;

	private static final long serialVersionUID = 1L;

	public ComerciosPK() {
		super();
	}

	public Integer getConvenio() {
		return this.convenio;
	}

	public void setConvenio(Integer convenio) {
		this.convenio = convenio;
	}

	public long getComercio() {
		return this.comercio;
	}

	public void setComercio(long comercio) {
		this.comercio = comercio;
	}

	@Override
	public boolean equals(Object o) {
		if (o == this) {
			return true;
		}
		if ( ! (o instanceof ComerciosPK)) {
			return false;
		}
		ComerciosPK other = (ComerciosPK) o;
		return (this.convenio == other.convenio)
			&& (this.comercio == other.comercio);
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int hash = 17;
		hash = hash * prime + ((int) (this.convenio ^ (this.convenio >>> 32)));
		hash = hash * prime + ((int) (this.comercio ^ (this.comercio >>> 32)));
		return hash;
	}

}
Entity
@Table(name="convenio.comercios")
public class Comercios extends Comercio implements Serializable {
	
	@Id
	private ComerciosPK pk;
	
	@ManyToOne 
	@JoinColumns(
			@JoinColumn(name="EMPRESA",referencedColumnName="EMPRESA", insertable=false, updatable=false)
	)
	private Empresa empresa;
	
	public Empresa getEmpresa() {
		return empresa;
	}

	public void setEmpresa(Empresa empresa) {
		this.empresa = empresa;
	}
	
	@Column(name="EMPRESA")
	private long nroEmpresa;
	
	@Column(name="TIPO_COMERCIO", length=1)
	private int tipoComercio;

	public int getTipoComercio() {
		return tipoComercio;
	}

public ComerciosPK getPk() {
		return this.pk;
	}

	public void setPk(ComerciosPK pk) {
		this.pk = pk;
	}
facade.persist(populaComercios());

omiti alguns get e set…

gugaa_df

Esse código não está setando no banco a coluna CONVENIO

albama

Guga , existe algumas coisas que JPA faz em relação a herança , inclusive há bastante discussões sobre assunto no blog da Caelum.

Sinceramente não concordo do jeito JPA faz, e acredito que os DBA’s devem ficar loucos.

Quando estou com um problema parecido com o seu na modelagem dos Entity, eu copio as classes e vou reescrevendo tudo novamente para verificar onde está dando o erro.

Veja, há uma complexidade na sua classe “class Comercios” :

  1. ela herda “extends Comercio” (verificar a criação do entity comercio)
  2. acessa Empresa empresa (verificar a criação do entity Empresa)
  3. tem uma chave composta ComerciosPK pk.

Sugiro que faça passo a passo, para verificar onde está emperrando, pelo menos assim você terá controle, e saberá onde está o erro.

Marco Aurélio
[email removido]

gugaa_df

Não há complexidade aonde vc citou, porque as heranças são só classes abstratas, não sao Entidades.
o único problema mesmo é somente a chave composta.

[email removido:
]Guga , existe algumas coisas que JPA faz em relação a herança , inclusive há bastante discussões sobre assunto no blog da Caelum.

Sinceramente não concordo do jeito JPA faz, e acredito que os DBA’s devem ficar loucos.

Quando estou com um problema parecido com o seu na modelagem dos Entity, eu copio as classes e vou reescrevendo tudo novamente para verificar onde está dando o erro.

Veja, há uma complexidade na sua classe “class Comercios” :

  1. ela herda “extends Comercio” (verificar a criação do entity comercio)
  2. acessa Empresa empresa (verificar a criação do entity Empresa)
  3. tem uma chave composta ComerciosPK pk.

Sugiro que faça passo a passo, para verificar onde está emperrando, pelo menos assim você terá controle, e saberá onde está o erro.

Marco Aurélio
[email removido]

albama

Ok , me manda a classe empresa , estou simulando aqui.

gugaa_df
@Entity
@Table(name="convenio.empresa")
public class Empresa extends br.com.cabal.entity.Empresa implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	@Id
	@NotFound(action=NotFoundAction.IGNORE)
	private long empresa;

	private Integer convenio;

	private String cnpj;

	@Column(name="RAZAO_SOCIAL")
	private String razaoSocial;

	@Column(name="NOME_CARTAO")
	private String nomeCartao;

	@Column(name="DIA_CORTE")
	private Integer diaCorte;

	@Column(name="DIA_PAGAMENTO")
	private Integer diaPagamento;
...//Tem mais outras propriedades. encapsulamento omitido.
albama
Estou interpretando as heranças como se fossem de classe abstratas. Pelo fato de não tê-las, vou tirar do codigo. Na empresa tirei
extends br.com.cabal.entity.Empresa
Não consegui usar : convenio no meu mysql
@Entity  
@Table(name="convenio.empresa")
Por isso deixei assim:
@Entity  
@Table(name="empresa")

Fiz a mesma coisa da classe comercios tirei o schema "convenio":

@Entity 
 @Table(name="convenio.comercios")

Segue as classes e a chave composta:

CLASSE EMPRESA ( sem getters e setters)
@Entity  
 @Table(name="empresa")  
 public class Empresa  implements Serializable {  
       
     private static final long serialVersionUID = 1L;  
       
     @Id  
     @NotFound(action=NotFoundAction.IGNORE)  
     private long empresa;  
   
     private Integer convenio;  
   
     private String cnpj;  
  
     @Column(name="RAZAO_SOCIAL")  
     private String razaoSocial;  
   
     @Column(name="NOME_CARTAO")  
     private String nomeCartao;  
   
     @Column(name="DIA_CORTE")  
     private Integer diaCorte;  
  
     @Column(name="DIA_PAGAMENTO")  
    private Integer diaPagamento;
Classe PK ( sem getter e setters)
@Embeddable  
 public class ComerciosPK implements Serializable {  
 private static final long serialVersionUID = 1L;
	 
 @Column(name="CONVENIO")  
  private Integer convenio;  
   
  @Column(name="COMERCIO")  
  private long comercio;
Classe comercios ( sem getter e setters) Está com chave composta. Verificar a anotaçao ManyToOne ( Join) , está dando erro.
@Entity 
 @Table(name="comercios")  
 public class Comercios implements Serializable {  
  private static final long serialVersionUID = 1L;
	@Id  
    private ComerciosPK pk;  
	
	 //@ManyToOne   
     //@JoinColumns(  
     //        @JoinColumn(name="EMPRESA",referencedColumnName="EMPRESA", insertable=false, updatable=false)  
     //) 
     /**TODO
      * Há algum problema com este mapeamento
      * favor verificar*/
	 @Column(name="EMPRESA")  
     private long nroEmpresa;  
       
     @Column(name="TIPO_COMERCIO", length=1)  
     private int tipoComercio;  


BASE DE DADOS

Empresa criada
[code]
# Table "empresa" DDL

CREATE TABLE `empresa` (
  `empresa` bigint(20) NOT NULL,
  `convenio` int(11) default NULL,
  `cnpj` varchar(255) default NULL,
  `RAZAO_SOCIAL` varchar(255) default NULL,
  `NOME_CARTAO` varchar(255) default NULL,
  `DIA_CORTE` int(11) default NULL,
  `DIA_PAGAMENTO` int(11) default NULL,
  PRIMARY KEY  (`empresa`)
) ENGINE=InnoDB DEFAULT CHARSET=latin
Classe com chave composta criada
# Table "comercios" DDL

CREATE TABLE `comercios` (
  `CONVENIO` int(11) NOT NULL,
  `COMERCIO` bigint(20) NOT NULL,
  `EMPRESA` bigint(20) default NULL,
  `TIPO_COMERCIO` int(11) default NULL,
  PRIMARY KEY  (`CONVENIO`,`COMERCIO`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
´

Marco Aurélio
[email removido]
[/code]

gugaa_df

Tentei te mandar um e-mail e nao consegui…
Bom, nao consegui ver diferença do seu código para o meu…
Em relação ao mapeamento, aqui está tudo correto, não aconteceu nenhum erro nada.
Estou tendo alguns probleminhas com a JPA, tem algum e-mail que eu possa te mandar?

Criado 26 de janeiro de 2009
Ultima resposta 27 de jan. de 2009
Respostas 20
Participantes 2