当我使用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,它将抛出类似标题描述的异常
我查看了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);
不会抛出异常,但是角色#1没有关联到userbean#1
任何人都可以就此提出一些建议吗?
答案 0 :(得分:29)
如果我们能够看到您将角色bean分配给用户和组的代码,那么确定原因会更容易。
一般来说,异常告诉我们的是该角色bean有两个版本(两个实例)。第一个更新,然后Hibernate命中第二个,并识别它是相同的标识符,但角色的不同分离版本。
Hibernate不确定哪个是正确的,并且在saveOrUpdate下,它会抛出异常让你知道。
Merge的合同的工作方式不同,因为它会假设您打算再次保存它(即合并我的所有更改),因此将重新附加第二个版本,合并所有更改,并保存任何更新。
我在博客上发表了关于SaveOrUpdate vs Merge的更多细节来解释发生了什么。
如果你想坚持使用SaveOrUpdate,你需要弄清楚你在作业中做了什么,导致将角色的不同实例分配给用户的角色集合而不是组。
否则,如果合并的效果对您有效(符合JPA标准),则使用它。