Hibernate equals and proxy
equals, hibernate, proxy
Solution
To be able to lazy-load the `a.b` association, Hibernate sets the `b` field in `a` to a proxy. The proxy is an instance of a class that extends B, but is not B. So, your equals() method will always fail when comparing a non-proxy B instance to a proxy B instance, because it compares the classes of both objects:
if (getClass() != obj.getClass())
return false;
In the case of Hibernate entities, you should replace this with
if (!(obj instanceof B)) {
return false;
}
Also, note that
- Hibernate recommends not implementing `equals()` and `hashCode()` by using the ID, but rather by using a natural identifier. Implementing it with IDs can cause problems because entities don't have an ID until they're saved and the ID is generated
- When using entity inheritance, the problem is even worse. Suppose B is a superclass of two sub-entities B1 and B2. Hiberante can't know which type (B1 or B2) is `a.b` before loading it. So `a.b` will be initialized to a proxy which is a subclass of B, but is not a subclass of B1 or B2. So the `hashCode()` and `equals()` methods should be implemented in B, but not be overridden in B1 and B2. Two B instances should be considered equal if they're instances of B, and have the same identifier.
Problem
I have one BaseEntity which abstracts id and version property. this class also implements hashcode and equals based on PK (id) property. ``` BaseEntity{ Long id; Long version; public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BaseEntity other = (BaseEntity) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } } ``` now two Entity A and B extends BaseEntity as below ``` A extends BaseEntity{ `B b` B getB(){return b;) void setB(B b){this.b=b;} } B extends BaseEntity{ } object b1; object a1; a1.set(b1); session.save(a1) //cascade save; ``` close session load a with lazy b and try a1.getB().equals(b1) gives false but if i compare with a1.getB().getId().equals(b1.getId()) then gives true strange!! i think it is because of java assist proxy object, anyway to resolve this?