Java 休眠:具有相同标识符值的不同对象已经与会话相关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3553200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate: different object with the same identifier value was already associated with the session
提问by user421851
Possible Duplicate:
Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session
可能重复:
休眠错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已经与会话相关联
when I use the DAO.update(userbean), session.SaveOrUpdate(e);
throw the Exception:different object with the same identifier value was already associated with the session
当我使用 DAO.update(userbean) 时,session.SaveOrUpdate(e);
抛出异常:具有相同标识符值的不同对象已经与会话相关联
the function is like next:
功能如下:
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 ;
}
the userbean is an instance of class UserBean
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> ();
}
every groupbean has a list of roles, which are not changed.
每个 groupbean 都有一个角色列表,这些角色不会改变。
in database, group and role is many-to-many mapping,
在数据库中,组和角色是多对多映射,
for example,
例如,
we have a groupbean#1, it's roles: rolebean#1, rolebean#2;
我们有一个 groupbean#1,它的角色是:rolebean#1,rolebean#2;
groupbean#2, which roles are rolebean#1.
groupbean#2,哪些角色是 rolebean#1。
now I create a new userbean#1, it's groups is groupbean#1 and if I want to add the rolebean#1 to userbean#1, it will throws the exception like the title descript
现在我创建了一个新的 userbean#1,它的组是 groupbean#1,如果我想将 rolebean#1 添加到 userbean#1,它将抛出异常,如标题描述
I look the server.log, and find that when I user DAO.save, the saveOrUpdate order is:
我查看了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
the cause of the exception is rolebean#1 has been saved twice in a session, and their identity is the same.
异常的原因是rolebean#1在一个会话中被保存了两次,并且他们的身份是一样的。
In the function save(E e), If I use
在函数 save(E e) 中,如果我使用
session.merge(e);
replace
代替
session.SaveOrUpdate(e);
will not throw exception, but the rolebean#1 is not assocaited to userbean#1
不会抛出异常,但 rolebean#1 不关联到 userbean#1
anyone can give some suggestions about this?
任何人都可以就此提出一些建议?
回答by Stevi Deter
It would be easier to identify the exact cause if we can see the code where you're assigning the role bean to both the user and then the group.
如果我们可以看到您将角色 bean 分配给用户和组的代码,那么确定确切原因会更容易。
In general, what the exception tells us is that there are two versions of that role bean (two instances). The first one gets updated, then Hibernate hits the second one, and recognizes it's the same identifier but a different detached version of the role.
通常,异常告诉我们该角色 bean 有两个版本(两个实例)。第一个被更新,然后 Hibernate 命中第二个,并识别出它是相同的标识符,但角色的不同分离版本。
Hibernate's not sure which is correct, and under saveOrUpdate, it throws an exception to let you know.
Hibernate 不确定哪个是正确的,在 saveOrUpdate 下,它会抛出一个异常让你知道。
Merge's contract works differently, in that it will assume you meant to save it again (i.e., merge all my changes), and thus will reattach the second version, merge all changes, and save any updates.
Merge 的合约工作方式不同,因为它会假设您打算再次保存它(即合并我的所有更改),因此将重新附加第二个版本,合并所有更改并保存所有更新。
I've blogged about SaveOrUpdate vs Mergewith some more detail to explain what's going on.
我在博客上写了关于SaveOrUpdate 与 Merge 的更多细节来解释发生了什么。
If you want to stick with SaveOrUpdate, you're going to need to figure out what you're doing in the assignment that's causing a different instance of the role to be assigned to the user's role collection versus to the groups.
如果您想坚持使用 SaveOrUpdate,您将需要弄清楚您在分配中做了什么,导致将不同的角色实例分配给用户的角色集合而不是组。
Otherwise, if the effects of merge work for you (which is in line with the JPA standard), then use it.
否则,如果合并的效果对您有用(符合 JPA 标准),则使用它。