0

I know this is an age-long topic with countless posts about it, but I can't seem to find a clear answer to this question.

When dealing with entities with natural IDs, why is an equals/hashCode implementation based on all relevant fields (as if it was a plain data object) seemingly not an option? This post, this post, and some of the answers in this Stack Overflow thread suggest to only use the natural ID in equals/hashCode. This does not seem to take into consideration comparisons against transient/detached entities. For instance, given the following class:

public class Currency {

    private String code; // e.g. "USD"
    private String name; // e.g. "United States Dollar"

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Currency other && Objects.equals(code, other.code);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(code);
    }
}

Equality check between Currency{code=USD, name=United States Dollar} and Currency{code=USD, name=Foobar Dollar} (if the latter is assumed to be transient/detached, then this situation is realistic) will yield true, which is probably not correct.

The "3rd option" in the previously linked SO thread, alongside its discussions about whether the equals/hashCode in that case is "broken" or not, lead me to believe that an implementation based on all relevant fields is valid after all, though it is not clear to me.

Clarification: "relevant" fields are those that represent the entity's properties, i.e. not fields that are some transient implementation detail, e.g. some cached computation.

If I have erred in any of my assumptions or have missed something obvious, please correct me :)

  • There is no clear answer as the 'right' implementation depends on what you need to use them for. Some try to put every property in the instance in equals and use it for test comparisons (verify serialization keeps the instance data the same). ID defines an entity, and using a hashcode on mutable properties is going to cause you issues if you ever put the instance in a hashmap/set, so you might as well use the immutable ID for it, and special methods to compare if values within two separate instances are the same if required. – Chris Sep 30 '22 at 18:56

0 Answers0