views:
75answers:
2The equals method in JobStateChange uses direct field access. Changing it to use getters for the various properties will fix the problem. You may also want to consider using the HibernateProxyHelper.getClassWithoutInitializingProxy
method when performing the instanceof
comparison.
For example, the JobStateChange.equals
method might look like:
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
} else if (!(HibernateProxyHelper.getClassWithoutInitializingProxy(obj)
instanceof JobStateChange)) {
return false;
}
JobStateChange candidate = (JobStateChange) obj;
return this.getState() == candidate.getState()
&& this.getActingUser().equals(candidate.getUser())
&& this.getDate().equals(candidate.getDate());
}
Likewise, the JobStateChange.hashCode()
method should also use getters (I would also recommend writing the hashCode
method to match the algorithm suggested by Joshua Bloch in Effective Java, Chapter 3 (starting on page 38), but that isn't really relevant to the question):
@Override
public int hashCode() {
return this.getState().hashCode()
+ this.getActingUser().hashCode()
+ this.getDate().hashCode();
}
Part of the "magic" behind Hibernate are dynamic proxies. In many cases, Hibernate creates (at run time) a subclass of your entity classes, and overrides the getter and setter methods of the persisted properties. Thus, you cannot reference the properties directly in equals
and hashCode
, but instead should access them using the property getters and setters, even internally in the entity class.
You were receiving a "unique constraint" error because Hibernate relies on the equals
method when persisting changes to a collection.
With the old equals method, the proxied JobStateChange
objects will never be equal to one another, or to non-proxied JobStateChange
objects. Thus, Hibernate thought that the existing elements in the stateChanges collection were new items, and attempted to insert them into the database. Since the rows in job_state
must be unique (defined by the primary key across all columns), a constraint volition was generated.