休眠:具有相同标识符值的不同对象已与会话相关联[重复]

Posted

技术标签:

【中文标题】休眠:具有相同标识符值的不同对象已与会话相关联[重复]【英文标题】:Hibernate: different object with the same identifier value was already associated with the session [duplicate] 【发布时间】:2011-04-02 23:08:48 【问题描述】:

可能重复:Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

当我使用 DAO.update(userbean) 时,session.SaveOrUpdate(e);throw 异常:具有相同标识符值的不同对象已与会话关联

函数如下:

    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 都有一个角色列表,这些角色不会更改。

在数据库中,组和角色是多对多的映射,

例如,

我们有一个 groupbean#1,它的角色:rolebean#1,rolebean#2;

groupbean#2,哪些角色是rolebean#1。

现在我创建了一个新的 userbean#1,它的组是 groupbean#1 如果我想将rolebean#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

异常的原因是rolebean#1在一个会话中被保存了两次,它们的身份是一样的。

在函数save(E e)中,如果我使用

session.merge(e);

替换

session.SaveOrUpdate(e);

不会抛出异常,但 rolebean#1 没有关联到 userbean#1

任何人都可以对此提出一些建议吗?

【问题讨论】:

【参考方案1】:

如果我们可以看到您将角色 bean 分配给用户和组的代码,则更容易确定确切原因。

一般来说,异常告诉我们的是该角色 bean 有两个版本(两个实例)。第一个得到更新,然后 Hibernate 命中第二个,并识别出它是相同的标识符,但角色的分离版本不同。

Hibernate 不确定哪个是正确的,在 saveOrUpdate 下,它会抛出异常让您知道。

Merge 的合约工作方式不同,它会假设您打算再次保存它(即合并我的所有更改),因此将重新附加第二个版本,合并所有更改并保存所有更新。

我已经写了一篇关于SaveOrUpdate vs Merge 的博客,其中提供了更多详细信息来解释正在发生的事情。

如果您想坚持使用 SaveOrUpdate,您将需要弄清楚您在分配中执行的操作导致将不同的角色实例分配给用户的角色集合而不是分配给组。

否则,如果合并的效果对您有用(符合 JPA 标准),请使用它。

【讨论】:

以上是关于休眠:具有相同标识符值的不同对象已与会话相关联[重复]的主要内容,如果未能解决你的问题,请参考以下文章

休眠错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

Grails NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

Struts / hibernate NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联

具有相同标识符值的不同对象已与保存时的会话错误相关联[重复]

memge和saveOrUpdate的区别