Identidade de entidades

9 respostas
rmendes08

Um dos gaps na ORM é a questão da identidade de uma entidade, segundo o livro do Gavin King, você pode comparar uma entidade:

  • por identidade de objeto ( == )
  • igualdade de valor ( .equals() )
  • identidade relacional ( PK )

mesmo assim, ainda me restou uma dúvida: como devemos implementar equals() e hashCode() para classes de entidades ? Por exemplo, uma classe Cliente. A equals() e hashCode() devem:

  • não serem sobrescritos,
  • implementar a igualdade de valor, comparando campo a campo
  • implementar a igualdade relacional, comparando apenas a PK ?

9 Respostas

lucaz.cabral

Rodolfo a meu ver isso depende de como vai comportar sua Entidade.
Se ela servir para registrar dados de tabelas em base de dados, melhor vc comparar por ID (PK)
Caso contrário, por ex uma pessoa (lembrando que sem heranças pra outras entidades), vc pode usar o cpf.
Não sei se fui claro mas espero que tenha entendido.
:lol:

P

Pensando em termos de ORM, eu sobrescrevo equals() e hashCode() verificando, na ordem:

  1. Igualdade relacional (PK);
  2. Igualdade de valor, comparando campo a campo;
rmendes08

lucaz.cabral:
Rodolfo a meu ver isso depende de como vai comportar sua Entidade.
Se ela servir para registrar dados de tabelas em base de dados, melhor vc comparar por ID (PK)
Caso contrário, por ex uma pessoa (lembrando que sem heranças pra outras entidades), vc pode usar o cpf.
Não sei se fui claro mas espero que tenha entendido.
:lol:

Entendi, mas nesse caso, considerando que Pessoa está mapeada para uma tabela, o campo CPF deve ser declarado com UNIQUE. Interessante essa opção também, de usar uma chave natural para prover identidade.

CarlosEduardoDantas

O cenário ideal seria implementar chaves naturais (ou business key como gostam de chamar) para equals() e hashCode(), não deixando o hibernate gerenciar seus ids.

Para cenários onde não é possível achar tais chaves, existem alternativas, como o Commons Id

http://commons.apache.org/sandbox/id/uuid.html

rmendes08

CarlosEduardoDantas:
O cenário ideal seria implementar chaves naturais (ou business key como gostam de chamar) para equals() e hashCode(), não deixando o hibernate gerenciar seus ids.

Para cenários onde não é possível achar tais chaves, existem alternativas, como o Commons Id

http://commons.apache.org/sandbox/id/uuid.html

Bom quer dizer que se eu implementar chaves naturais para equals e hashCode eu não devo ter campos mapeados com @Id ?

CarlosEduardoDantas

rmendes08:
CarlosEduardoDantas:
O cenário ideal seria implementar chaves naturais (ou business key como gostam de chamar) para equals() e hashCode(), não deixando o hibernate gerenciar seus ids.

Para cenários onde não é possível achar tais chaves, existem alternativas, como o Commons Id

http://commons.apache.org/sandbox/id/uuid.html

Bom quer dizer que se eu implementar chaves naturais para equals e hashCode eu não devo ter campos mapeados com @Id ?

"Never use the database identifier to implement equality; use a business key, a combination of unique, usually immutable, attributes. The database identifier will change if a transient object is made persistent. If the transient instance (usually together with detached instances) is held in a Set, changing the hashcode breaks the contract of the Set. Attributes for business keys don't have to be as stable as database primary keys, you only have to guarantee stability as long as the objects are in the same Set." (Hibernate Reference Documentation v. 3.1.1).

"We recommend implementing equals() and hashCode() using Business key equality. Business key equality means that the equals() method compares only the properties that form the business key, a key that would identify our instance in the real world (a natural candidate key)" (Hibernate Reference Documentation v. 3.1.1).

editado

concluindo…

In other words, use a natural key for equals() and hashCode(), and use a Hibernate-generated surrogate key for the object’s id.

rmendes08

Entendi. Até então não tinha pensado nesse problema das Collections também. Mas então, na falta das chaves naturais então, a alternativa seria implementar o equals com igualdade de valor …

Carlos, não entendi como usar UUID nesse contexto, poderia me explicar ?

jfaerman

Suponha que voce não tenha/não queira usar uma “chave de negocio”.
Usar o ID gerado pelo banco pode ser ruim porque todo objeto transiente seria igual ( pk = 0 ou null ).
Usando o UUID voce pode atribui-lo direto na instanciação com baixissimo risco de duplicar chaves e sem contenção (threads esperando pra gerar chave, o que acontece quando a sequence / tabela tá lockada).

CarlosEduardoDantas

A idéia seria ter uma classe que automaticamente nos fornece o id e já implementa o equals() e hashCode(), com isso, toda classe que dependa desta abordagem pode estender. Segue um artigo explicando melhor esta abordagem

http://tim.oreilly.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=3

Criado 13 de setembro de 2011
Ultima resposta 13 de set. de 2011
Respostas 9
Participantes 5