Hibernate: a different object with the same identifier value was already associated with the session
People working with Hibernate might be familiar with the below error.
This exception is generated when we try to load an instance object in session which has been already loaded by hibernate.
Easier said than done.
Hibernate considers two persistent entities identical if the two rows of the table can be said identical.
Above error could be generated in many ways and there may be various solutions on net like using session merge etc to get away with the problem.
I will discuss here the reason for me getting this problem and the way I resolved it.
Below is the code which generated the exception for me.
Following is the method which caused the exception
The following code was calling the above method.
If you see in the test case above, the object "ImageCreativesStat" is created and passed to method "registerStats".
"ImageCreativesStat" object is not loaded through hibernate, so its a disconnected object for hibernate.
Therefore when we execute the below line
It loads a connected dataset. Hence when we execute the line
it gives us an exception because the hibernate already holds an identical object in the session.
Changing the method "registerStats" to the following resolved the issue.
I Hope this helps.
Please note, this is one of the causes and not the only cause for this exception.
org.springframework.orm.hibernate3.HibernateSystemException:
a different object with the same identifier value was already
associated with the session:
nested exception is org.hibernate.NonUniqueObjectException:
a different object with the same identifier value was already
associated with the session
This exception is generated when we try to load an instance object in session which has been already loaded by hibernate.
Easier said than done.
Hibernate considers two persistent entities identical if the two rows of the table can be said identical.
Above error could be generated in many ways and there may be various solutions on net like using session merge etc to get away with the problem.
I will discuss here the reason for me getting this problem and the way I resolved it.
Below is the code which generated the exception for me.
Following is the method which caused the exception
@Transactional(propagation=Propagation.REQUIRED)
public void registerStats(ImageCreativesStat imageCreativeStat){
Listlst = getIcsByDimainAndCreative(imageCreativeStat);
if(lst.size() == 1){
imageCreativeStat.setId(lst.get(0).getId());
imageCreativeStat.setImp_delivered(lst.get(0).getImp_delivered() + imageCreativeStat.getImp_delivered());
imageCreativeStat.setClick_delivered(lst.get(0).getClick_delivered() + imageCreativeStat.getClick_delivered());
}
getHibernateTemplate().saveOrUpdate(imageCreativeStat);
}
The following code was calling the above method.
@Test
public final void testRegisterStats() {
ImageCreativesStat ics = new ImageCreativesStat();
ics.setCreative_id(123);
ics.setDomain_id(456);
Assert.assertTrue("PASSED : When no criteria specified ", icsDAO.getIcsByDimainAndCreative(ics).size() == 0);
ics.setImp_delivered(9);
ics.setClick_delivered(98);
icsDAO.registerStats(ics);
Assert.assertEquals("PASSED One record in the DB", 1, icsDAO.getIcsByDimainAndCreative(ics).size());
ics.setImp_delivered(10);
ics.setClick_delivered(11);
icsDAO.registerStats(ics);
Assert.assertEquals("PASSED One record in the DB", 1, icsDAO.getIcsByDimainAndCreative(ics).size());
ics = icsDAO.getIcsByDimainAndCreative(ics).get(0);
Assert.assertEquals(19, ics.getImp_delivered());
Assert.assertEquals(109, ics.getClick_delivered());
}
If you see in the test case above, the object "ImageCreativesStat" is created and passed to method "registerStats".
"ImageCreativesStat" object is not loaded through hibernate, so its a disconnected object for hibernate.
Therefore when we execute the below line
Listlst = getIcsByDimainAndCreative(imageCreativeStat);
It loads a connected dataset. Hence when we execute the line
getHibernateTemplate().saveOrUpdate(imageCreativeStat);
it gives us an exception because the hibernate already holds an identical object in the session.
Changing the method "registerStats" to the following resolved the issue.
@Transactional(propagation=Propagation.REQUIRED)
public void registerStats(ImageCreativesStat imageCreativeStat){
ImageCreativesStat ics;
Listlst = getIcsByDomainAndCreative(imageCreativeStat);
if(lst.size() == 1){
ics = lst.get(0);
ics.setImp_delivered(ics.getImp_delivered() + imageCreativeStat.getImp_delivered());
ics.setClick_delivered(ics.getClick_delivered() + imageCreativeStat.getClick_delivered());
getHibernateTemplate().update(ics);
}else{
getHibernateTemplate().save(imageCreativeStat);
}
}
I Hope this helps.
Please note, this is one of the causes and not the only cause for this exception.
Thanks a lot for the post, I hit this exact error on an application in production and this fix took care of it.
ReplyDeleteI am glad that it helped you and thanks for taking time to post the comment
DeleteNice explanation.
ReplyDeletejadjinakadi janare !
ReplyDeletepora jaff na daffa............ :O
ReplyDeletegood exaple
ReplyDeleteThen why do we have the saveOrUpdate method?
ReplyDeleteThis is a lifesaver post.
ReplyDelete