(JPA) Algum exemplo real (Chave-Composta)

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…

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

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

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.

Para pesquisar a chave composta:

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

Marco Aurélio

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);

??

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

é 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…

é 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…

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

é 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…

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

Por favor coloque seu código aqui.

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…

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

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
aureliorodrigues@gmail.com

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.

[quote=albama@bol.com.br]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
aureliorodrigues@gmail.com[/quote]

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

@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.

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
[/code]


Classe com chave composta criada
[code]
# 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
´
[/code]

Marco Aurélio
aureliorodrogues@gmail.com