How to implement a Hibernate-safe equals() method using instanceof and accessors (getters) in Eclipse
When coding in Java you often want to check to see if two objects are 'equal'. This might range from a check to see if just one attribute is the same (the ID for example), or a complete comparisons of all attributes all the way up to ensuring that two objects are referencing the same instance of a particular class.
There is a lot of information out on the internet about how to write a correct
Here are some tips that I learnt the hard way today when trying to test some JPA/Hibernate-backed objects for equality:
So go from this:
Technorati Tags: Java, Joshua Bloch, Effective Java, equals, hashCode, Eclipse, instanceof, Andrew Beacock
There is a lot of information out on the internet about how to write a correct
equals()
method (and the corresponding hashCode()
) but I think Joshua Bloch's explanation from his excellent Effective Java book is the best.Here are some tips that I learnt the hard way today when trying to test some JPA/Hibernate-backed objects for equality:
- Don't use the default settings of Eclipse's built-in generator for equals() and hashCode() - it generates equals methods based on checking whether the two objects are from the same class (using getClass()), Hibernate proxies everything so this will never match
- Don't use Eclipse's built-in generator at all - it's alternative option to "Use 'instanceof' to compare types" is more correct than it's default but still doesn't work for Hibernate classes
- Do ensure that instanceof is used when ever checking if two objects have a similar background, the Hibernate proxies seem to respect this check so the proxies are instances of the classes that they proxy.
- Do ensure that you use the accessors (getters) when getting the member variable values rather than the variables directly as the values maybe lazy loaded so
id
may actually returnnull
whereasgetId()
will return the actual value from the database.
So go from this:
@Overrideto this:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Person))
return false;
final Person other = (Person) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@OverrideA blog post from wenhu on the subject as well as some information from my colleagues were the sources for this post and the remedy to today's headache!
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Person))
return false;
final Person other = (Person) obj;
if (getId() == null) {
if (other.getId() != null)
return false;
} else if (!getId().equals(other.getId()))
return false;
if (getName() == null) {
if (other.getName() != null)
return false;
} else if (!getName().equals(other.getName()))
return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
return result;
}
Technorati Tags: Java, Joshua Bloch, Effective Java, equals, hashCode, Eclipse, instanceof, Andrew Beacock
Comments
What if I don't like hash. I really don't like the taste. I prefer haggis.
Ergo, if I don't like hash do I have to write a hashCode() method?
This may be a bit too much personal information: when I ate hash in the past, it used to get stuck in my Nokia phone. Only the receiver portion.
(In a way, it was good. I could still talk but didn't have to listen.)
Sincerely,
Nhoj Yelruc
because (obj instaceof MyClass) returns false anyway in case obj has value null, no matter its type.
Maarten Hogendoorn, JConsultancy.com
In BTW, having id in equals is not a good idea. Always have business key fields (i.e fields which makes object unique)