Problem dotyczy Twojego hashCode
wdrożenie na Price
.
Implementacje obu equals
i hashCode
często źle, ponieważ opierają swoją równość i obliczanie skrótu wyłącznie na wartości ID
jednostki tylko. W przypadku nowo utworzonych instancji, w których ID
to @GeneratedValue
wynik, to nie zadziała.
W Twoim przypadku za każdym razem, gdy dodajesz nową Price
wystąpienie do Twojego Set<>
, ten sam hashCode
wartość jest obliczana, ponieważ każda nowa instancja ma null ID
, więc są zastępowane.
Dostosuj swoje equals
i hashCode
implementacje:
@Override
public boolean equals(Object object) {
if ( object == this ) {
return true; // instance equality
}
if ( object == null || object.getClass() != getClass() ) {
return false;
}
final Price other = Price.class.cast( object );
if ( getId() == null && other.getId() == null ) {
// perform equality check against all non-id attributes
}
else {
// perform equality check only on id
}
}
@Override
public int hashCode() {
final HashCodeBuilder hcb = new HashCodeBuilder( 17, 37 );
if ( id == null ) {
hcb.append( price );
hcb.append( discount );
// other fields
}
else {
// only identity basis
hcb.append( id );
}
return hcb.toHashCode();
}
Daje to pewność, że podczas porównywania dwóch nietrwałych obiektów Price
, ich porównanie/hash opiera się na atrybutach niezidentyfikowanych. Po utrwaleniu metody będą opierać swoje porównanie/hash wyłącznie na wartości tożsamości, co pozwala na dwa przypadki, w których jedna została zmodyfikowana, a druga nie musi się równać.