異常:
org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session:
日志節選:
2012-05-16 16:55:51,354[CatchExceptionFilter.java:88 :ERROR] CatchExceptionFilter捕獲到異常...
org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [cn.ac.iscas.core.entity.pm.cm.CmPlanBaseline#587]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [cn.ac.iscas.core.entity.pm.cm.CmPlanBaseline#587]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:679)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
at cn.ac.intec.entity.orm.impl.SessionImpl.saveOrUpdate(SessionImpl.java:133)
at cn.ac.intec.entity.orm.impl.SessionImpl.insertOrUpdate(SessionImpl.java:125)
at cn.ac.intec.entity.orm.impl.SessionImpl$$FastClassByCGLIB$$550f49cd.invoke(<generated>)
觸發場景,解決方案:
1. show業務操作,開啟一個session ,從中查出一些實體,這時某個實體是存在於session中的持久化對象。通過業務邏輯將此實體用於頁面展示。此時這個session並未關閉。
2. 這時執行一步save業務邏輯,將上一步獲得的實體id傳回后台 。這時通過new的方式創建了一個 臨時對象,並且我將 傳回的id作為主鍵付給了臨時對象。然后調用了session.save(obj); 方法 。。。拋出異常。
原因很簡單,session中有2個oid一樣的對象,hibernate不知道該讓哪個持久化到庫里。當時解決思路也很清晰,直接 clear();清空一下 session緩存不就Ok了。但是 clear打擊面太廣了(慎用!)。其他一些“無辜”對象也被殺掉,導致其他業務無法進行了。
后來在session中發現一個evict方法,“定點清除”對象緩存。這下就好了,先用傳回來的id用get方法(其實這里用load方法也行反正都是從緩存中加載)獲得session里的持久化實體,然后殺掉,再保存臨時實體。沒問題了。