mai 03

Equals com Objeto do tipo proxy do hibernate

Há tempos que não posto nada, estou devendo muita coisa. Mas essa aqui eu tava me ferrando e acho que vale a pena registrar.

A situação é a seguinte: Tenho uma entidade A que se relaciona com a entidade B  em um relacionamento OneToOne, porém não quero utilizar o carregamento eager padrão para este relacionamento. Para resolver isso base adicionar a propriedade fetch=FetchType.LAZY na anotação OneToOne.  Mas como dizia Joseph Climber, a vida é uma caixinha de surpresas. Não é que pra minha surpresa o cache do hibernate resolveu funcionar em um select e manteve um objeto do tipo B que eu já tinha carregado a partir de um do tipo  A. Ou seja, no meio da listagens de objetos do tipo retornados do meu select * , tinha um intruso do tipo lazy do hibernate no meio da listagem WTF???!! . Ou seja, meu equals (gerado pelo eclipse) estava executando a instrução if (getClass() != obj.getClass()) e retornando true, uma vez que aquele bendito objeto lazy intruso não era da mesma classe!!

Agora chega de blablabla e vamos pras soluções:

Solução 1:

Devemos adicionar a seguinte verificação:

Onde tínhamos:  if (getClass() != obj.getClass())

Devemos ter agora:

Class<?> objProxyClass = 
HibernateProxyHelper.getClassWithoutInitializingProxy(obj);
 if (getClass() != obj.getClass() && getClass()!= objProxyClass )

e voi là , na chamada ao método getClassWithoutInitializingproxy é retornada a classe original do meu proxy e o if seguinte funciona sem problema algum!

Solução 2:

Essa solução foi retirada da documentação do hibernate

 if( !(obj instanceof B)) return false;

Essa é bem mais simples e também funciona!!

Agora fica a seu critério a utilização de uma ou de outra.

Lembrando que toda vez que seu objeto tiver a possibilidade de ser um proxy do hibernate nunca utilize diretamente os atributos no equals, faça as comparações sempre utilizando os métodos GETTERS!!!

É isso, se alguém souber uma situação que uma solução ou outra não atenda pode comentar aí, até a próxima.