Dúvida Tabela com chave composta

1 resposta
Jedi_FeniX

Estudando o hibernate e fazendo uns testes com o mesmo no netbeans vi que quando tem uma tabela com uma chave composta tem que se criar uma classe para essa chave.
Alguém poderia explicar o motivo disto, porque ainda não ficou muito claro este conceito.

1 Resposta

Lavieri

O motivo é pq o provedor de persistencia não tem como comparar + de 1 propriedade, então isso tem que ser feito explicitamente por vc...

O objeto PK que vc criar tem que implementar corretamente os métodos equals/hashCode para o funcionamento correto da aplicação...

é uma exigencia do JPA que toda entidade tenha uma chave primaria única... o Netbeans mapea a classe totalmente em separado, o que na minha opinião é ruim, pois vc acaba tendo que fazer algo como

entrada.getId().getPessoa();
entrada.getId().getHorario();

Forma que o netbeans mapea uma calsse dessas

@Entity
public class Entrada implements Serializable {
    @EmbeddedId
    private EntradaPK id;
    @ManyToOne
    private Local local;
    private String observacao;
    //... métodos getters/setters
}
@Embeddable
public class EntradaPK implements Serializable {
   private Pessoa pessoa;
   private Date horario;

   //...métodos getters/setters
   
   private boolean isDefinido() { //o ID só se define quando há pessoa e horário
      return getPessoa() != null && getHorario() != null;
   }

   public boolean equals(Object obj) {
      if (!isDefinido())
          return false; //se o proprio objeto não se define, ele não é igual a ninguem
      if (!(obj instanceof EntradaPK)
          return false;
      EntradaPK other = (EntradaPK)obj;
      return getPessoa().equals(other.getPessoa()) 
                && getHorario().equals(other.getHorario());
   }
   
   public int hashCode() {
      if (!isDefinido())  //se não é definido, não há necessidade de calcular hash.
         return super.hashCode();
      
      int h = 35;
      h = 35*h + getPessoa().hashCode();
      h = 35*h + getHorario().hashCode();
      return h;
   }
}

você pode usar uma abordagem bem mais facil, no uso da classe, que é o @IdClass, com ele vc cria o objeto em separado, que mostra para o provedor de persistência como comparar 2 objetos, mas não estraga seu objeto

nesta segunda abordagem vc pode usar direto

entrada.getPessoa();
entrada.getHorario();

pois a classe é definida assim
@Entity
@IdClass(EntradaPK.class) //aqui eu defindo a chave composta
public class Entrada implements Serializable {
    @Id
    private Pessoa pessoa; //esse campo é parte da chave composta
    @Id
    private Date horario; //esse campo tambem
    @ManyToOne
    private Local local;
    private String observacao;
    //... métodos getters/setters
}

vc continua tendo que escrever o EntradaPK, porem o objeto Entrada fica mais claro... e o objeto EntradaPK vai existir apenas para informar ao provedor de persistencia como comparar com equals e hashCode... e neste caso do uso de @IdClass o objeto EntradaPK não precisa ser anotado como @Embedable

Ps.: Se não entender equals/hahscode, entra no meu blog na minha assinatura q la tem explicações...

Criado 12 de agosto de 2009
Ultima resposta 12 de ago. de 2009
Respostas 1
Participantes 2