Проблемът е във вашия hashCode
внедряване на Price
.
Реализации на двете equals
и hashCode
често грешни, защото основават изчисленията си за равенство и хеш единствено на стойността на ID
на обекта само. В случаите на новосъздадени екземпляри, при които ID
е @GeneratedValue
резултат, това няма да работи.
Във вашия случай всеки път, когато добавяте нова Price
екземпляр към вашия Set<>
, същият hashCode
стойността се изчислява, защото всеки нов екземпляр има нулев ID
, така че те продължават да се сменят.
Коригирайте вашето equals
и hashCode
реализации:
@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();
}
Това гарантира, че когато се сравняват два несъхранени обекта на Price
, тяхното сравнение/хеш се основава на атрибутите, които не са идентични. След като се запазят, методите ще базират своето сравнение/хеширане само срещу стойността на идентичността, позволявайки два случая, когато единият е бил променен, а другият не трябва да се равнява на същото.