четверг, 24 сентября 2009 г.

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

   Ошибка возникает потому что пытаемся сохранить/удалить/проапдейтить объект из другой сессии, который уже загружен в нашей сессии(закэширован).
 Лечение:
1) 100% лекарство использовать hibernateTemplate.merge(object);
2) 100% лекарство которое приводит к обнулению всего кэша

      hibernateTemplate.flush();
      hibernateTemplate.clear();
      hibernateTemplate.saveOrUpdate(object);


3)   лекарство может не помочь

      hibernateTemplate.evict(object); - убирает объекты из кэша сравнивая их по объектной ссылке
      hibernateTemplate.saveOrUpdate(object); - проверяет наличие объектов в кэше(прежде чем их сохранить) по айдишнику. Вывод: такая пара смысла не имеет(ну, имеет смысл в рамках одной сессии и совсем для другого).

      Можно написать так:
      Class dataObjectClass = object.getClass();
      long id = object.getId();
      T dataObject = (T) hibernateTemplate.get(dataObjectClass, id);

      if (dataObject != null) {
        hibernateTemplate.evict(dataObject );
      }

Но это спасёт нас только в том случае - если в ентитях нигде нету перекрёстных ссылок. Если они есть - то при каскадном сохранении будут ентити добавляться в кэш по нескольку раз и в результате получим тот же иксэпшн(Зы: иксэпшн будет валиться непосредственно при комите транзакции и всякие flush перед evict тут непомогут).

    
  
4) делать всё в одной сессии
5)загрузить по id,  выставить необходимые поля, сохранить

2 комментария:

  1. http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html

    ОтветитьУдалить
  2. http://pro-programmers.blogspot.com/2009/03/hibernate-nonuniqueobjectexception.html

    ОтветитьУдалить