6

Having such problem. Loaded collection of 2 objects (by primary key, using criteria). Then iterating them in the loop. When processing first object, somewhere very very far from this loop, is loaded object by same primary key as second object in loop. Here I see that System.identityHashCode() are different for this 2 objects. When processing second object from loop and trying to save it I get exception:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

Trying to simulate this problem with simple object, loading , modifying, once more loading by PK, saving with different transaction propogation-s I always get same object instance... Could you please tell when it is possible to get second object instance in same session loading by PK?

whatswrong
  • 2,203
  • 4
  • 25
  • 36
  • Check out these - http://stackoverflow.com/questions/1074081/hibernate-error-org-hibernate-nonuniqueobjectexception-a-different-object-with and http://stackoverflow.com/questions/15005914/hibernate-org-hibernate-nonuniqueobjectexception-a-different-object-with-the-s – Shailendra Dec 16 '13 at 08:49
  • Also please make sure, that you have overridden methods `equals` and `hashCode` in your entity class. – n1ckolas Dec 16 '13 at 09:33

2 Answers2

4

In my situation problem was because: Firstly I have loaded some entity 'A' by primary key. Then I have loaded another entity 'B' using some criteria which through hbm mapping referenced this same (by PK) entity 'A' (for example B->some entity C->A) and hibernate didn't use already loaded 'A' entity, but loaded or created it secondly (I put breakpoint in entity 'A' constructor), thus in single session we have 2 entities with same PK but different instances. Trying to save entity 'A' we get exception 'NonUniqueObjectException'. Loading entity 'B' was somewere very very far away and under some conditions to reproduce and identify the problem. To find such places faster easily put breakpoint in 'NonUniqueObject' constructor and find who is loading this entity second time. By the way after I loaded entity 'B' I didn't try to call B->C->A, lazy='proxy' or without lazy at all, which means load C per request. Some mysteries to me...

whatswrong
  • 2,203
  • 4
  • 25
  • 36
0

An easy way to implement equals() and hashcode() with a single primary key field like a String let's say or an Integer would be like so:

public boolean equals(Object obj) {
   if (obj == null) { return false; }
   if (obj == this) { return true; }
   if (obj.getClass() != getClass()) {
     return false;
   }
   ThisClass that = (ThisClass) obj;
   return this.id.equals( that.id );
}
public int hashCode() {
    returns id.hashCode();
}

for compound keys you're going to want to use code like this:

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/HashCodeBuilder.html

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/EqualsBuilder.html

Robert Beltran
  • 495
  • 3
  • 9
  • I thought it was an anti-pattern to implement equals and hashCode on entity classes? A persistence context maintains at most one managed entity per PK anyways, so overriding these methods only serve to confuse developers. – MrBackend Jan 06 '14 at 14:40