Você está na página 1de 8

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

CHAVE COMPOSTA (Composite Key).

Imagine que apenas o ID no seja suficiente para definir a chave primria da sua entidade. Como fazer com que o JPA entenda esse mapeamento? Vamos utilizar como exemplo uma classe Carro. Imagine um sistema onde para se identificar um carro, necessrio o nmero do chassi. Vamos supor que um novo requisito chegou e alm do chassi ser necessrio o cdigo de identificao do motor. Ser necessrio criar uma classe para fazer o trabalho da chave composta. Existem algumas normas que sua classe de chave composta deve seguir: 1. Deve ter um construtor sem argumentos 2. Deve implementar a interface java.io.Serializable 3. Deve sobrescrever os mtodos equals e hashCode Vamos ver como ficar o cdigo da classe CarroPK:
package br.uniban.entity.pk; import java.io.Serializable; public class CarroPK implements Serializable { private static final long serialVersionUID = -8858744663237932877L; private String chassisSerialNumber; private String motorSerialNumber; public CarroPK(){} @Override public boolean equals(Object obj) { if(!(obj instanceof CarroPK)){ CarroPK carPk = (CarroPK) obj;

if(! carPk.getChassisSerialNumber().equals(chassisSerialNumber)) { return false; } if(! carPk.getMotorSerialNumber().equals(motorSerialNumber)){ return false; } return true; } return false; }

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

@Override public int hashCode() { return chassisSerialNumber.hashCode() + motorSerialNumber.hashCode(); } public String getChassisSerialNumber() { return chassisSerialNumber; } public void setChassisSerialNumber(String chassisSerialNumber) { this.chassisSerialNumber = chassisSerialNumber; } public String getMotorSerialNumber() { return motorSerialNumber; } public void setMotorSerialNumber(String motorSerialNumber) { this.motorSerialNumber = motorSerialNumber; } }

Agora vamos criar nossa classe Carro:


package br.uniban.entity; import import import import import javax.persistence.Column; javax.persistence.Entity; javax.persistence.Id; javax.persistence.IdClass; javax.persistence.Table;

import br.uniban.entity.pk.CarroPK; @Entity @Table(name="tb_carro", schema="uniban") @IdClass(value=CarroPK.class) public class Carro { @Id private String chassisSerialNumber; @Id private String motorSerialNumber; @Column(name="str_nome", length = 80) private String nome; public String getChassisSerialNumber() { return chassisSerialNumber; } public void setChassisSerialNumber(String chassisSerialNumber) { this.chassisSerialNumber = chassisSerialNumber; } public String getMotorSerialNumber() { return motorSerialNumber; } public void setMotorSerialNumber(String motorSerialNumber) {

Tpicos Avanados de Programao - Ano:2011


this.motorSerialNumber = motorSerialNumber; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } }

Prof.Fbio Rener

Repare que em nossa entidade Carro, adicionamos a anotao @IdClass que indica qual ser a classe responsvel pela chave primaria da entidade. Veja o cdigo da classe JPAPersist que ir inserir um objeto da classe Carro em nosso banco de dados:
package br.uniban.main; import javax.persistence.*; import br.uniban.entity.Carro; public class JPAPersist { /** * @param args */ public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("aula8PU"); EntityManager em = emf.createEntityManager(); try{ em.getTransaction().begin(); Carro car = new Carro(); car.setChassisSerialNumber("9BW DA05X6 1 T050136"); car.setMotorSerialNumber("ABC123"); car.setNome("Ford Focus"); em.persist(car); em.getTransaction().commit(); } catch(Exception e){ System.out.println(e.getMessage()); } finally{ em.close(); } } }

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

Console:

MySql :

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

E como consultar uma entidade que tem a chave primria composta? Vejamos a classe JPAConsulta :
package br.uniban.main; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import br.uniban.entity.Carro; import br.uniban.entity.pk.CarroPK; public class JPAConsulta { /** * @param args */ public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("aula8PU"); EntityManager em = emf.createEntityManager(); try{ em.getTransaction().begin(); CarroPK carPK = new CarroPK(); carPK.setChassisSerialNumber("9BW DA05X6 1 T050136"); carPK.setMotorSerialNumber("ABC123"); Carro car = em.find(Carro.class, carPK); System.out.println("----------------------------------"); System.out.println(car.getNome()); System.out.println("----------------------------------"); em.getTransaction().commit(); } catch(Exception e){ System.out.println(e.getMessage()); } finally{ em.close(); } } }

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

Vamos ver outra forma de mapear uma chave primaria composta. Repare que atualmente ns temos os mesmos campos dentro da classe CarroPK e Carro. Ambos contm o cdigo do chassi e o cdigo do motor. Podemos fazer uma pequena alterao no cdigo para solucionar isso, vejamos a classe Carro2PK.
package br.uniban.entity.pk; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class Carro2PK implements Serializable { private static final long serialVersionUID = -8858744663237932877L; @Column private String chassisSerialNumber; @Column private String motorSerialNumber; public Carro2PK(){} @Override public boolean equals(Object obj) { if(!(obj instanceof Carro2PK)){ Carro2PK carPk = (Carro2PK) obj; if(! carPk.getChassisSerialNumber().equals(chassisSerialNumber)) { return false; } if(! carPk.getMotorSerialNumber().equals(motorSerialNumber)){ return false; } return true; } return false; } @Override public int hashCode() { return chassisSerialNumber.hashCode() + motorSerialNumber.hashCode(); } public String getChassisSerialNumber() { return chassisSerialNumber; } public void setChassisSerialNumber(String chassisSerialNumber) { this.chassisSerialNumber = chassisSerialNumber; } public String getMotorSerialNumber() { return motorSerialNumber; }

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

public void setMotorSerialNumber(String motorSerialNumber) { this.motorSerialNumber = motorSerialNumber; } }

Vejamos a entidade Carro2 como fica:

package br.uniban.entity; import javax.persistence.*; import br.uniban.entity.pk.Carro2PK; @Entity @Table(name="tb_carro", schema="uniban") public class Carro2 { @EmbeddedId private Carro2PK carroPK; @Column(name="str_nome", length=80) private String nome; public Carro2PK getCarroPK() { return carroPK; } public void setCarroPK(Carro2PK carroPK) { this.carroPK = carroPK; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } }

Persistindo Carro2:

package br.uniban.main; import javax.persistence.*; import br.uniban.entity.Carro2; import br.uniban.entity.pk.Carro2PK; public class JPAPersist2 { /** * @param args */ public static void main(String[] args) {

Tpicos Avanados de Programao - Ano:2011

Prof.Fbio Rener

EntityManagerFactory emf = Persistence.createEntityManagerFactory("aula8PU"); EntityManager em = emf.createEntityManager(); try{ em.getTransaction().begin(); Carro2PK pk = new Carro2PK(); pk.setChassisSerialNumber("RT7 FGH5XF 1 FF0969"); pk.setMotorSerialNumber("WED345"); Carro2 car = new Carro2(); car.setNome("RANGER GLX "); car.setCarroPK(pk); em.persist(car); em.getTransaction().commit(); } catch(Exception e){ System.out.println(e.getMessage()); } finally{ em.close(); } } }

Pequenas alteraes foram feitas:

1. Na classe Carro2PK agora existe a anotao @Column. Esses sero a partir de agora os atributos mapeados no banco de dados. Foi adicionada tambm a anotao @Embeddeable informando que essa classe pode ser incorporada em outra classe. 2. Na classe Carro2 foram retirados os atributos e substitudos por um atributo da classe Carro2PK. Foi retirado tambm a anotao @IdClass. Agora colocamos uma outra anotao chamada @EmbeddedId que informa ao JPA que os campos a serem utilizados viro de dentro da classe Carro2PK.

Você também pode gostar