Eu realmente pensava que o gerador de código do Eclipse era bacaninha... Mas de vez em quando ele faz umas coisas meio toscas, que dão trabalho pra gente descobrir depois :(
Dessa vez é rápido. Bem rápido. Digamos que você tem uma determinada classe persistente do Hibernate:
Talvez, ao você mandar que a sua IDE implemente os demais métodos (gets, sets, equals e hashcode), você se depare com uma construção parecida no equals():
Suponha que a variável de instância pai seja mapeada como um relacionamento lazy-load, ou seja, carregado do banco somente quando explicitamente necessário. Agora imagine duas instâncias da classe Pessoa, que nós chamaremos de a e b. De maneira semelhante, imagine que ambas, a e b apontem como pai uma mesma instância da classe Pessoa, aqui chamada de c.
Em algum momento dentro do seu código fonte, você fez uma chamada ao método getPai() na instância a. Devido ao lazy-load, o hibernate se encarregaria de carregar este relacionamento para você. Mas o que ocorreria quando você realizasse um a.equals(b)? A variavel de instância a.pai já estaria carregada, e referenciando c, enquanto que b.pai ainda não estaria inicializada, referenciando null. E então, ao passar pelo trecho de código do método equals mostrado acima, o resultado do equals() seria false, apesar das linhas da tabela Pessoa, referentes às nossas instâncias a e b estarem referenciando o mesmo pai.
Isso tudo, porque durante a geração de código, sua IDE não realizou o encapsulamento das variáveis membro. É isso mesmo ou eu fiquei bêbado com 500 ml de suco de laranja hoje? Eu sempre achei que o equals() acima deveria, na verdade, ser o abaixo:
public class Pessoa { private Pessoa pai; private Pessoa mãe; private String nome; private Date nascimento; //Getters e Setters }
Talvez, ao você mandar que a sua IDE implemente os demais métodos (gets, sets, equals e hashcode), você se depare com uma construção parecida no equals():
public boolean equals(Object obj) { if (this == obj) return true; if (! super.equals(obj)) return false; if (! getClass().equals(obj.getClass())) return false; Pessoa other = (Pessoa) obj; ... if (pai == null) { if (other.pai != null) return false; } else if (pai.equals(other.pai)) return false; ... }
Suponha que a variável de instância pai seja mapeada como um relacionamento lazy-load, ou seja, carregado do banco somente quando explicitamente necessário. Agora imagine duas instâncias da classe Pessoa, que nós chamaremos de a e b. De maneira semelhante, imagine que ambas, a e b apontem como pai uma mesma instância da classe Pessoa, aqui chamada de c.
Em algum momento dentro do seu código fonte, você fez uma chamada ao método getPai() na instância a. Devido ao lazy-load, o hibernate se encarregaria de carregar este relacionamento para você. Mas o que ocorreria quando você realizasse um a.equals(b)? A variavel de instância a.pai já estaria carregada, e referenciando c, enquanto que b.pai ainda não estaria inicializada, referenciando null. E então, ao passar pelo trecho de código do método equals mostrado acima, o resultado do equals() seria false, apesar das linhas da tabela Pessoa, referentes às nossas instâncias a e b estarem referenciando o mesmo pai.
Isso tudo, porque durante a geração de código, sua IDE não realizou o encapsulamento das variáveis membro. É isso mesmo ou eu fiquei bêbado com 500 ml de suco de laranja hoje? Eu sempre achei que o equals() acima deveria, na verdade, ser o abaixo:
public boolean equals(Object obj) { if (this == obj) return true; if (! super.equals(obj)) return false; if (! getClass().equals(obj.getClass())) return false; Pessoa other = (Pessoa) obj; ... if (getPai() == null) { if (other.getPai() != null) return false; } else if (getPai().equals(other.getPai())) return false; ... }