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里的持久化實體,然后殺掉,再保存臨時實體。沒問題了。