Подтвердить что ты не робот

Hibernate: другой объект с тем же значением идентификатора уже был связан с сеансом

Возможный дубликат:
Ошибка Hibernate: org.hibernate.NonUniqueObjectException: другой объект с тем же значением идентификатора уже был связан с сеансом

когда я использую DAO.update(userbean), session.SaveOrUpdate(e); throw Exception: другой объект с тем же значением идентификатора уже был связан с сеансом

функция следующая:

    public E save(E e) {
    Session session = null;
    try {
        session = sessionFactory.openSession();
        log.debug("session="+session.hashCode()+" save "+e);
        session.SaveOrUpdate(e);  //here throws exception 
        session.flush();
    }
    catch (Exception e1) {
        log.err("Cannot open hibernate session "+ e1.getMessage()+" cause : "+e1.getCause());
        e1.printStackTrace();
    }
    finally { if ( session != null ) session.close(); session = null;}
    return e ;
}

userbean - это экземпляр класса UserBean

public class UserBean{
   private List<GroupBean> groups = new ArrayList<GroupBean> ();
   private List<RoleBean> roles = new ArrayList<RoleBean> ();
}

public class GroupBean{
private List<RoleBean> roles = new ArrayList<RoleBean> ();
}

каждая группа имеет список ролей, которые не изменяются.

в базе данных, группа и роль - это многозначное отображение,

например,

у нас есть groupbean # 1, его роли: rolebean # 1, rolebean # 2;

groupbean # 2, роли которых - rolebean # 1.

теперь я создаю новый userbean # 1, это группы groupbean # 1 и если я хочу добавить рольbean # 1 в userbean # 1, он выдает исключение, подобное описанию названия

Я смотрю server.log и обнаруживаю, что когда пользователь DAO.save, заказ saveOrUpdate выглядит следующим образом:

userbean#1
|---|-----------***userbean.groups
|     |     groupbean#1
|     |         groupbean.roles
|     |             rolebean#1  # save relebean#1 the first time
|     |             ---done rolebean#1
|     |         ------done all rolebeans of group.roles
|     |     ---done groupbean#1
|     |-----------done all groupbeans of userbean.groups
|---|-----------***userbean.roles
     |      rolebean#1          # save rolebean#1 the second time, and throws exception here!
     |      ----done rolebean#1
     |      .....
     |-----------done all rolebeans of userbean.roles

причиной исключения является рольbean # 1, которая была сохранена дважды в сеансе, и их идентификация одинакова.

В функции save (E e), если я использую

session.merge(e);

заменить

session.SaveOrUpdate(e);

не будет генерировать исключение, но рольbean # 1 не привязана к userbean # 1

Кто-нибудь может дать некоторые предложения об этом?

4b9b3361

Ответ 1

Было бы легче определить точную причину, если мы сможем увидеть код, в котором вы назначаете роль bean как пользователю, так и группе.

В общем, что говорит об исключении, существует две версии этой роли bean (два экземпляра). Первый обновляется, затем Hibernate обращается ко второму и распознает его как тот же идентификатор, но другую отдельную версию роли.

Hibernate не уверен, что это правильно, и в saveOrUpdate он выдает исключение, чтобы вы знали.

Слияние контракта работает по-разному, поскольку предполагается, что вы хотели его снова сохранить (т.е. объединить все мои изменения) и, таким образом, повторно подключить вторую версию, слить все изменения и сохранить любые обновления.

Я писал о SaveOrUpdate vs Merge с более подробной информацией, чтобы объяснить, что происходит.

Если вы хотите использовать SaveOrUpdate, вам нужно будет выяснить, что вы делаете в задании, что приводит к тому, что другой экземпляр роли будет назначен для коллекции ролей пользователя по сравнению с группами.

В противном случае, если эффекты слияния работают для вас (что соответствует стандарту JPA), используйте его.