Problemet er med din hashCode
implementering på Price
.
Implementeringer af begge equals
og hashCode
ofte forkert, fordi de udelukkende baserer deres ligheds- og hashberegning på værdien af enhedens ID
kun. I tilfælde af nyoprettede tilfælde, hvor ID
er en @GeneratedValue
resultat, vil dette ikke virke.
I dit tilfælde, hver gang du tilføjer en ny Price
instans til dit Set<>
, den samme hashCode
værdien beregnes, fordi hver ny instans har et null ID
, så de bliver ved med at blive udskiftet.
Juster din equals
og hashCode
implementeringer:
@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();
}
Dette sikrer, at når man sammenligner to ikke-vedvarende objekter af en Price
, deres sammenligning/hash er baseret på ikke-identitetsattributter. Når først de er blevet ved, vil metoderne basere deres sammenligning/hash kun på identitetsværdien, hvilket giver mulighed for to tilfælde, hvor den ene er blevet ændret, og den anden ikke skal svare til det samme.