Problém je s vaším hashCode
implementace na Price
.
Implementace obou equals
a hashCode
často chybné, protože svůj výpočet rovnosti a hash zakládají výhradně na hodnotě ID
entity pouze. V případech nově vytvořených instancí, kde je ID
je @GeneratedValue
výsledek, tohle nebude fungovat.
Ve vašem případě pokaždé, když přidáte novou Price
instance do vaší Set<>
, stejný hashCode
hodnota se vypočítá, protože každá nová instance má prázdné ID
, takže se neustále nahrazují.
Upravte equals
a hashCode
implementace:
@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();
}
Tím je zajištěno, že při porovnávání dvou nestálých objektů Price
, jejich porovnání/hash je založeno na neidentitních atributech. Jakmile metody přetrvají, založí své srovnání/hash pouze na hodnotě identity, což umožní dva případy, kdy jeden byl upraven a druhý se nemusí rovnat stejnému.