First Case : Lazy Initialization Proxies:
The proxies may often contain all the information in your persistent class, and so they appear to be the real deal. When we query these objects they return all the information in the underlying proxied object. We run into a couple issues however if we use standard implementations of equals in our persistent class:
Lets say your equals() method in the class Noodle looks like this:
public boolean equals(Object obj) {
if(this == obj)
return true;
if(getClass() != obj.getClass() )
return false;
........
}
At this point we see that equals will never succeed - the class Noodle will never equal the Hibernate Proxy class. When you try to update an object from the collection, Hibernate never finds the object it needs to update because the equals implementation always fails. If you need to implement a comparison of class you could use one of the following :
this.getClass().isAssignableFrom(obj.getClass())
or
HibernateProxyHelper.getClassWithoutInitializingProxy(obj)
If you use hibernate annotations in your pojos, this additional Hibernate checking should not be too invasive or out of place. One other mistake people often make when implementing equals is to try to access the fields directly off of the object:
public boolean equals(Object obj) {
....
Noodle other = (Noodle)obj;
if(! this.attributeA.equals(other.attributeA) )
return false;
....
}
Here we run into 2 issues:
1. The cast may throw a ClassCastException.
2. The attributeA may have limited visibility.
A Solution that worked for me and covers the situation where the other object is not a proxy:
public boolean equals(Object other) {
if ( this == obj )
return true;
if( obj == null )
return false;
if( getClass().equals( obj.getClass() ) {
Noodle other = (Noodle)obj;
if( getId().equals( other.getId() )
return true;
}
else if( obj instanceof HibernateProxy ) {
if(HibernateProxyHelper.getClassWithoutInitializingProxy(obj).equals(this.getClass() ) {
Noodle other = (Noolde)obj;
if( getId().equals( other.getId() )
return true;
}
}
return false;
}
Second Case: You used Load() instead of get():
There may be times when you want to use load() - when you are simply adding references to an object in a collection for instance. But when you are pulling an object specifically to use its values, you should switch to using get() - as the attributes are guaranteed to be available.
There may be times when you want to use load() - when you are simply adding references to an object in a collection for instance. But when you are pulling an object specifically to use its values, you should switch to using get() - as the attributes are guaranteed to be available.