Category Archives: Hibernate

Hibernate – Non Unique Object Exception

Non Unique Object Exception : a different object with the same identifier value was already associated with the session

Scenario:

When we try to save an object in hibernate, we may get this error under following cases:

sessionObject

 

//SAMPLE 1

MyObject someObjectICreateThatIsNotManaged = new MyObject();
someObjectICreateThatIsNotManaged.setId(1); //Yes setId should not be changable by code, but this is just for demonstration purposed
//(Now within a Transaction/Session)
MyObject objectWithID1 = em.find(1,MyObject.class));
em.saveOrUpdate(someObjectICreateThatIsNotManaged); // This will get that exception thrown because objectWithID1 was loaded and is managed by the EntityManager, and when you then tried to “persist” someObjectICreateThatIsNotManaged, that object has the same id of 1 in it, and someObjectICreateThatIsNotManaged != objectWithID1

//SAMPLE 2

MyObject objX1 = hibernateTemplate.get(objX2.class,new Integer(1));

MyObject objX2 = new MyObject(1);

objX2.setValue(b);

hibernateTemplate.saveOrUpdate(objX2); //throws error

 

Reason for Error:

Here this save or update will throw you NonUniqueObjectException because, in hibernate session, you are creating an object with an ID 1 initially. Then you are taking fetching another object of same type with the same ID 1. As Hibernate Session’s understanding it considers both objects as same object or object that is already associated with the session.

In sample 2 you can see that Hibernate Session is fetching instance of objX1 having ID 1. In this case, if we try to save the objX2 having same ID 1 the exception will be thrown as both the objects are similar in terms of ID (Key that should be unique).

Solution:

We can use different strategies to solve this issue.

  • We can use merge() method available in Hibernate Session instead of using save or update method.
  • Programmatic way

MyObject objX2 = hibernateTemplate.get(objX2.class,new Integer(1));

if (objX2 == null){

objX2 = new MyObject(1);

}

objX2.setValue(b);

hibernateTemplate.saveOrUpdate(objX2);

 

FYI:: Automatic State Detection

According to “Automatic state detection”

saveOrUpdate() does the following:

  • if the object is already persistent in this session, do nothing
  • if another object associated with the session has the same identifier, throw an exception (NonUniqueObjectException in our case)
  • if the object has no identifier property, save() it
  • if the object’s identifier has the value assigned to a newly instantiated object, save() it
  • if the object is versioned (by a <version> or <timestamp>), and the version property value is the same value assigned to a newly instantiated object, save() it
  • otherwise update() the object

and merge() is very different:

  • if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
  • if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
  • the persistent instance is returned
  • the given instance does not become associated with the session, it remains detached

 

Reference: Coderanch.com, pro-programmers.blogspot.com

Advertisement