JSFアプリケーションでは、時々Hibernate NonUniqueObjectException(種類がorg.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
)が発生します。時間のほとんどは、これらのエラーは、次のシナリオに起因するものである:ビジネス・ロジックのデータベース Hibernate 3でNonUniqueObjectExceptionをデバッグする方法は?
- ロードオブジェクトを、に隠された他の呼び出しがあります同じオブジェクトをリロードするデータベース
- 元のオブジェクトを変更して永続化してください。
- 例外を取得します。
アプリが非常に大きいので、データベースへの2回目の呼び出しが完了した時点を把握することは難しいことがあります。 SQLトレースを使用していても、いくつかのコールが存在する可能性があり、それでも良いものを見つける必要があります。
コード内のどこからでも例外をスローするそのメソッドcheckUniqueness
を呼び出すことができればいいですが、簡単なショートカットがないようです。誰かがトリックを知っていますか?
import org.hibernate.SessionFactory;
import org.hibernate.engine.EntityKey;
import org.hibernate.event.EventSource;
import org.hibernate.persister.entity.EntityPersister;
/**
* @author aldian
*
*/
public class HibernateDebug {
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
HibernateDebug.sessionFactory = sessionFactory;
}
public static String checkUniqueness(Object entity, Long id) {
try {
org.hibernate.classic.Session currentSession = sessionFactory.getCurrentSession();
if (currentSession instanceof EventSource) {
EventSource eventSource = (EventSource) currentSession;
eventSource.getPersistenceContext().unproxyAndReassociate(entity);
EntityPersister persister = eventSource.getEntityPersister(entity.getClass().getName(), entity);
EntityKey key = new EntityKey(id, persister, eventSource.getEntityMode());
eventSource.getPersistenceContext().checkUniqueness(key, entity);
return "OK";
}
} catch (Exception e) {
return e.getMessage();
}
return "NOT OK";
}
}
注それが対応するBeanでのSessionFactoryを注入するようにします(例えば、バネ用)にアプリを初期化するものは何でも設定する必要があります。