A anotação @EqualsAndHashCode
que usa o atributo Long como pk
pode causar algum comportamento inesperado quando usado com estrutura baseada em hash (como HashSet).
por exemplo.:
<strong i="9">@Entity</strong>
@EqualsAndHashCode(of = "pk")
class Foo {
<strong i="10">@Id</strong>
private Long pk;
private LocalDate createdAt;
}
<strong i="13">@Entity</strong>
class Foo {
<strong i="14">@Id</strong>
private Long pk;
private LocalDate createdAt;
public int hashCode() {
int PRIME = true;
int result = 1;
Object $pk = this.getPk();
int result = result * 59 + ($pk == null ? 43 : $pk.hashCode());
return result;
}
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}
Portanto, quando a instância com pk = null e outra com pk = 43, ela retornará o mesmo código hash e poderá ser considerada a mesma em estrutura baseada em hash, o que não é.
E no caso de usar o OmniFaces ListConverter que usa toString
temos o mesmo problema.
Talvez retorne um hashcode da instância do objeto em vez de uma constante codificada
Você já pegou esse cenário, ou conhece alguma forma de contornar essa situação?!
Informação da versão
Então quando a instância com pk = null e outra com pk = 43, ela retornará o mesmo código hash
Isso não importa. Além disso, sempre haverá colisões de hash, não importa o que você escolher.
Observe que Arrays.hashCode
, String.hashCode
e muitos outros produzem toneladas de colisões, desnecessariamente.
Talvez retorne um hashcode da instância do objeto em vez de uma constante codificada
No meu código escrito manualmente, estou afirmando que ele não é chamado antes que um id
seja atribuído. Isso é certamente estranho, mas todas as alternativas também são.
Seria possível criar um parâmetro de anotação que informasse qual valor deve ser usado quando o PK for nulo, neste caso. Por padrão 43.
Isso daria mais controle ao desenvolvedor.
@EqualsAndHashCode(of = "pk", ifAnyNull = -1)
Portanto, usará -1 em vez de 43, para qualquer campo que fosse nulo
43 é provavelmente tão bom quanto qualquer outro número, e melhor que -1, 0 e 1. Torná-lo configurável adiciona carga de manutenção para um valor agregado muito baixo.
Usar o hashcode Identity para null quebraria o contrato de igualdade.
Comentários muito úteis
43 é provavelmente tão bom quanto qualquer outro número, e melhor que -1, 0 e 1. Torná-lo configurável adiciona carga de manutenção para um valor agregado muito baixo.
Usar o hashcode Identity para null quebraria o contrato de igualdade.