Composite Element Must Implement equals() and hashCode()
ID |
java.hibernate_equals_in_composite_elements |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
best-practice, hibernate, orm, reliability |
Description
Reports composite-element classes used with @ElementCollection that do not implement both equals(Object) and hashCode(). Hibernate relies on value equality for set semantics and dirty-checking in element collections. Without these methods, duplicates cannot be detected and changes may be lost.
Rationale
Element collections map value objects directly into a collection table. Hibernate compares old and new states using equals() to determine which rows to insert, update, or delete. When equals() and hashCode() are missing, Object identity comparison is used instead, causing Hibernate to delete and re-insert all rows on every flush.
// Bad: composite element without equals/hashCode
class Tag {
private String name;
private String value;
}
@Entity
class Product {
@Id Long id;
@ElementCollection
Set<Tag> tags;
}
Remediation
Implement both equals(Object) and hashCode() in every class used as a composite element in an @ElementCollection:
// Good: composite element with proper equals/hashCode
class Tag {
private String name;
private String value;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Tag)) return false;
Tag that = (Tag) o;
return Objects.equals(name, that.name)
&& Objects.equals(value, that.value);
}
@Override
public int hashCode() {
return Objects.hash(name, value);
}
}