How do you handle object equality for java objects managed by hibernate? In the ‘hibernate in action’ book they say that one should favor business keys over surrogate keys.
Most of the time, i do not have a business key. Think of addresses mapped to a person. The addresses are keeped in a Set and displayed in a Wicket RefreshingView (with a ReuseIfEquals strategy).
I could either use the surrogate id or use all fields in the equals() and hashCode() functions.
The problem is that those fields change during the lifetime ob the object. Either because the user entered some data or the id changes due to JPA merge() being called inside the OSIV (Open Session in View) filter.
My understanding of the equals() and hashCode() contract is that those should not change during the lifetime of an object.
What i have tried so far:
- equals() based on hashCode() which uses the database id (or super.hashCode() if id is null). Problem: new addresses start with an null id but get an id when attached to a person and this person gets merged() (re-attached) in the osiv-filter.
- lazy compute the hashcode when hashCode() is first called and make that hashcode @Transitional. Does not work, as merge() returns a new object and the hashcode does not get copied over.
What i would need is an ID that gets assigned during object creation I think. What would be my options here? I don’t want to introduce some additional persistent property. Is there a way to explicitly tell JPA to assign an ID to an object?
Regards
Using the
idof an entity is not a good idea because transient entities don’t have an id yet (and you still want a transient entity to be potentially equal to a persistent one).Using all properties (apart from the database identifier) is also not a good idea because all properties are just not part of the identity.
So, the preferred (and correct) way to implement equality is to use a business key, as explained in Java Persistence with Hibernate:
Maybe I missed something but for an Address, the business key would typically be made of the street number, the street, the city, the postal code, the country. I don’t see any problem with that.
Just in case, Equals And HashCode is another interesting reading.