6

I have been trying to reason about the best way to handle whether it is generally good practice to implement hashcode and equals on entities (I mean entity in the general sense but in most cases it will be a JPA entity).

In Chapter 24 of the Hibernate manual http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html it says this...

Identify natural keys for all entities, and map them using . Implement equals() and hashCode() to compare the properties that make up the natural key.

It makes sense to have .equals and .hashcode include only these natural keys but what if you have more than one instance of the same entity (same natural id thus same hashcode)? It seems like this practice could have subtle implications elsewhere in your application. Has anybody tried this before on a large scale?

benstpierre
  • 32,833
  • 51
  • 177
  • 288

2 Answers2

6

I've tried this before on a large scale (or at least in an application that heavily uses hibernate). It's a good idea.

It makes sense to have .equals and .hashcode include only these natural keys but what if you have more than one instance of the same entity (same natural id thus same hashcode)? It seems like this practice could have subtle implications elsewhere in your application.

This is what it's meant for. You typically want multiple instances of the same entity to succeed when comparing .equals, and yes, it has implications elsewhere. IMO those implications are that things would work as expected.

mrvisser
  • 924
  • 5
  • 9
3

There are times when you want Equals to compare all properties and times when you want Equals to be just the key. We've had a lot more success using helper classes that are explicit so there isn't ambiguity as to what's being compared.

ByKeyComparer.Equals...
ByPropertiesComparer.Equals...

or

Entity1.EqualsByKey...
Entity1.EqualsByProperties...
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
  • 1
    What sense does it make to be equal by key but not equal by properties? It's like being equal by reference but not by value. – Vladimir Gritsenko Dec 18 '09 at 16:59
  • 3
    new entities will not have a primary key (if you are using surrogates which is the standard way). So equals would not work for new entities if you are using the key to compare. – Arthur Thomas Dec 18 '09 at 17:01
  • which method do you use for the persistent classes `equals()` and `hashcode()` methods then? A choice needs to be made for these since they will be invoked by Collection or Hibernate code. – matt b Feb 10 '11 at 17:08
  • 1
    @matt b, for equals() and hashcode() I would recommend sticking to default ref based implementations. Equals by keys can change over time for new entities and would be equal incorrectly for new entities, and thus would not be appropriate. – Samuel Neff Feb 10 '11 at 17:39
  • Another helpful utility method would be something like `containsById`. – wrschneider Jan 09 '12 at 15:08