Wiki cleanup in progress: If you're having trouble finding something, read these tips.

Troubleshooting Hibernate

NonUniqueObjectException

What to do if you see an exception like the following

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [archive:org.openmrs.Role#System Developer]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:590)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
...

This usually means that you have loaded an object into your hibernate session that is a duplicate of an object you also have around as a detached instance, and you then try to reattach the attached instance.

Here is an example of code that Does Not Work

// Opening a form, i.e. controller.formBackingObject()
User user = Context.getUserService().getUser(12);

// Next when the form is submitted, i.e. controller.onSubmit()
// at this point user is detached
for (String roleUserShouldHave : request.getParameterValues("role")) {
Role role = Context.getUserService().getRole(roleUserShouldHave); // This is the problem
user.addRole(role);
}

Context.getUserService().updateUser(user); // This throws org.hibernate.NonUniqueObjectException

The issue here is that in the problem line we are fetching an object from the database that we already have a detached reference to via the user object. This exception would not be thrown if updateUser was doing a session.merge(user), since that just copies the state of the user object into the database. But doing session.saveOrUpdate(user) tries to reattach the detached user object, which fails if one of its dependant detachd objects is already in the session as an attached object.

Here is one solution, meant to be illustrative rather than elegant:

for (String roleUserShouldHave : request.getParameterValues("role")) {
Role role = null;
for (Role test : user.getRoles())
if (test.equals(roleUserShouldHave)
role = test; // it is safe to use the detached object
if (role h1. null)
Role role = Context.getUserService().getRole(roleUserShouldHave); // only do this if there is no detached object
user.addRole(role);
} Could not synchronize database state with session, and other batch commit issues ==

When working with transactions that contain several changes, it is sometimes difficult to determine which sql stmt in the batch is the cause of problem. In these situations hibernate is often less then helpful: setting hibernate.show_sql=true in the runtime properties may help. In these situations, the helpful trick is to set the hibernate batch size to 0 in runtime properties via: hibernate.jdbc.batch_size=0

For example, without the setting, the error may look something like this:

With hibernate.jdbc.batch_size=0, the error message recorded is:

Labels

cleanup cleanup Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.