Dodge Hibernate Coding Mistakes with Scertify's Code Analysis
Our Hibernate repository currently contains 30 rules. It works as an add-on for Scertify, our audit & refactoring tools suite. Some of the rules are related to the detection of possible bugs, other treat of maintainability or performance. In this article, we're going to present 4 rules that deal with a famous Hibernate's usage problem : the implementation of equals() and hashCode() methods.
What's the problem?
Equals and hashCode are used to compare objects. The default implementation of equals compares the object's address in memory. This is good as long as your objects are in memory, but Hibernate's goal is precisely to move them out of memory. Within a Hibernate session, Hibernate takes care of managing objects equality between a persistent identity and a Java identity.
However, when dealing with objects that come from different sessions, Hibernate can't do it. That's why it is necessary to override equals and hashCode.
This is our rule n°1 : HbEntitiesMustImplementEqualsHashCode detects any Hibernate entity that does not implement both methods. We also have HbEmbeddableEntitiesMustImplementEqualsHashCode that does the same for embeddable entities.
First step to solve it : implement equals()
So, I have a User and I want to implement the equals() method. I can just use its Id...
Ooops, or can't I? Indeed, if your Id is generated (as it is likely to be), it will be assigned once the object is persisted. Before that, all non-persisted entities have the same null id. So you could experience strange equality results... The good solution is to rely on the objects business fields to compare them, like the first name and the last name of my user.
This is our rule n°3 : HbEntitiesEqualsMustAvoidIDField detects usage of id field in equals().
Second step to solve it : implement hashCode()
I'm now ready to implement hashCode(). The Java language requires that if a.equals(b), then a.hashCode() is the same as b.hashCode(). As a consequence, I must use the same fields in hashCode() as I used in equals(). This may seem trivial for simple entities, but through evolution of an entity, this can be easy to forget to add a new field to one of the method.
This is our rule n°4 : HbEntityEqualsAndHashCodeUseDifferentFields detects equals and hashCode methods that use different fields.
To sum up, with this four rules you should be able to prevent a good deal of bugs related to incorrect usage of equals and hashCode in Hibernate entities. Have you already encountered such problems? Do you think there should be more rules regarding the implementation of these two methods? Please let us know in the comments!
Oh, and we have presented four of our thirty Hibernate rules, so that leaves plenty of interesting stuff to talk about : stay tuned!
About Scertify™ for Hibernate
Scertify™ for Hibernate is a product add-on for Scertify™. It includes a repository of 30 exclusive coding rules and best practices for Hibernate and JPA-based ORM frameworks. This rules repository works with both the Scertify Professional edition on the developers' IDE (Eclipse), and the Scertify Enterprise edition in continuous integration (Maven and CLI).
If you are interested or just curious, you can give it a try :
» See features