Embeddable Must Implement equals() and hashCode()

ID

java.hibernate_equals_in_embeddable

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

best-practice, hibernate, orm, reliability

Description

Reports @Embeddable classes that do not declare both equals(Object) and hashCode(). Hibernate relies on value equality to detect changes to embedded components during dirty-checking. Without these methods, modifications to embedded objects may go undetected and never be persisted.

Rationale

Embedded components (value objects) are mapped as part of the owning entity’s table. Hibernate compares the previous state with the current state using equals() to decide whether an UPDATE statement is needed. When equals() and hashCode() are missing, Object.equals() (identity comparison) is used instead, and Hibernate may either miss real changes or issue spurious updates.

// Bad: @Embeddable without equals/hashCode
@Embeddable
public class Address {
    private String street;
    private String city;
    private String zipCode;
}

Remediation

Implement both equals(Object) and hashCode() in every @Embeddable class, comparing all persistent fields that define the component’s value identity.

// Good: @Embeddable with proper equals/hashCode
@Embeddable
public class Address {
    private String street;
    private String city;
    private String zipCode;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Address)) return false;
        Address that = (Address) o;
        return Objects.equals(street, that.street)
            && Objects.equals(city, that.city)
            && Objects.equals(zipCode, that.zipCode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(street, city, zipCode);
    }
}