Entity equals()/hashCode() References @Id Field
ID |
java.hibernate_id_equals_hashcode |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
hibernate, orm, reliability |
Description
Reports @Entity classes where equals() or hashCode() references the @Id field. The JPA identifier is null for transient (unsaved) entities and changes upon persist(), breaking the contract of equals/hashCode for hash-based collections.
Rationale
When an entity is added to a HashSet before being persisted, its @Id is null, yielding one hash code. After persist(), the @Id is assigned, changing the hash code. The entity can no longer be found in the set, causing silent data loss. The same problem occurs when detaching and re-attaching entities.
// Bad -- @Id used in equals/hashCode
@Entity
class User {
@Id private Long id;
@Override
public boolean equals(Object o) {
return Objects.equals(id, ((User) o).id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
Remediation
Use a stable, immutable business key (e.g., email, UUID, natural key) or rely on the default Object identity:
// Good -- business key
@Entity
class User {
@Id private Long id;
@Column(unique = true) private String email;
@Override
public boolean equals(Object o) {
return Objects.equals(email, ((User) o).email);
}
@Override
public int hashCode() {
return Objects.hash(email);
}
}