2010-08-24 42 views
14

可能重复:
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);扔例外情况:具有相同标识符值的不同对象已与会话相关联

函数如下:

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,它会抛出之类的标题DESCRIPT

我看起来异常在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进行了会话被保存两次,他们的身份是一样的。

在功能保存(E E),如果我使用

session.merge(e); 

更换

session.SaveOrUpdate(e); 

不会抛出异常,但rolebean#1不assocaited到的UserBean#1

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

回答

27

如果我们可以看到代码将角色bean分配给用户和组,然后再将组分配给代码,那么确定确切原因会更容易。

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

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

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

我已经写了一些关于SaveOrUpdate vs Merge的更多详细信息来解释发生了什么。

如果你想坚持使用SaveOrUpdate,你需要弄清楚你在分配中做了什么,导致角色的不同实例被分配给用户的角色集合而不是组。

否则,如果合并的效果为您工作(这符合JPA标准),然后使用它。

相关问题