今天上午碰到了一個從沒碰到的問題。就是程序在添加的時候報了個NonUniqueObjectException 異常。
于是乎上網查了些資料,發現原因是:所以這個原因一般也不會發生的,一般發生重復保存或更新對象時。我自己的解決問題是很簡單了。因為在代碼重多添了 一個保存的動作,所以才造成了 這個異常發生,當去掉這個動作,一切就ok了。
在網上看了不少有類似情況的網友發的帖子,總結了下解決的辦法:
1) 如果用的 hibernate 2, 需要在get/load/query到持久化对象,赋上新的属性值,再 save/update/saveOrupdate.
对以上代码就是:不能 new 一个session中已存在OID的对象,直接
detail.setSubjectId(1000L);
session.save(detail);
session.save()一个持久化对象时,会转化成update调用。
2) 使用 hibernate 3 的 merge 方法. session.merge(newDetail)即可,它会在 session 缓存中找到持久化对象,把新对象的属性赋过去,再保存原session中的持久化对象。
如果在session或数据库中没有的对象,用merge方法的话,它也能够帮你把记录 insert 到表中,相当于 save 方法。
3)一個專家給的意見,
session.evict(objPO);//一下
或者在update之前session.clear();//一下,不过就都是权宜之计:(
主要是session没有及时关闭的导致的。
上面是一个简单的例子,实际业务中可能是经过一番复杂的操作后自己也很难搞清楚 new 的一个新对象在 session/数据库中是否已存在。所以第一种方法你需要清楚你的每一个对象状态,第二种方法在 hibernate 3 中就比较通用一些。
附 hibernate javadoc 对 session.merge() 方法的注释:
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge".
這個問題還需要繼續跟蹤深入學習,有相同經歷或有更好的解決辦法的,請跟貼,讓我們也學習下啊。