错误原因

A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]] with root cause
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]

大意可以理解成在hibernate的更新操作时发生了主键冲突;我这里是由于多对多的关系导致的。因为Privilege和Role之间我的更新是直接 new 多个Privilege然后赋值给Role的Set,这是最根本的原因。要知道hibernate在session中判别实体是通过该实体的主键唯一性判别的。我的错误dao层方法:

public void updateRole(Role role) {
getHibernateTemplate().update(role); }

service层方法:

public void editRole(Role role, String[] privilege_ids) {
Set<Privilege>set=new HashSet<>();
for (String id : privilege_ids) {
Privilege privilege=new Privilege();
privilege.setPrivilege_id((long) Integer.parseInt(id));
set.add(privilege);
}
role.setPrivileges(set);
roleDao.updateRole(role);

如果犯了和我相同的错误的话可以尝试使用

getHibernateTemplate().merge(role);

如果是操纵session操作的话使用

session.merge(role);

下面是hibernate的merge方法的具体实现

    @Override
public <T> T merge(final T entity) throws DataAccessException {
return executeWithNativeSession(new HibernateCallback<T>() {
@Override
@SuppressWarnings("unchecked")
public T doInHibernate(Session session) throws HibernateException {
checkWriteOperationAllowed(session);
return (T) session.merge(entity);
}
});
}

hibernate有关merge官方解释:

<T> T org.springframework.orm.hibernate5.HibernateTemplate.merge(T entity) throws DataAccessException

Copy the state of the given object onto the persistent objectwith the same identifier. Follows JSR-220 semantics. 

Similar to saveOrUpdate, but never associates the givenobject with the current Hibernate Session. In case of a new entity,the state will be copied over as well. 

Note that merge will not update the identifiersin the passed-in object graph (in contrast to TopLink)! Considerregistering Spring's IdTransferringMergeEventListener ifyou would like to have newly assigned ids transferred to the originalobject graph too.

  参照某位大佬的解释:

session.merge()方法会首先发送一句select语句,去数据库端获取UserInfo持久化标识所对应的表记录;然后自动生成一个持久化状态的UserInfo实体,与脱管状态的UserInfo实体做比较是否有所改变;一旦发生了改变,才会发送update语句执行更新。而按执行顺序,若两句session.merge()方法针对同一个脱管状态的UserInfo实体,那其结果只会执行最后一个session.merge()方法所发出的update语句。即使执行了session.merge()方法,UserInfo实体依然是脱管状态,

错误日志

严重: Servlet.service() for servlet [my-one] in context with path [/myone-web] threw exception [Request processing failed; nested exception is org.springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]] with root cause
org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:)
at org.hibernate.engine.spi.CascadingActions$.cascade(CascadingActions.java:)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:)
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$(JdbcResourceLocalTransactionCoordinatorImpl.java:)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:)
at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:)
at com.sun.proxy.$Proxy46.editRole(Unknown Source)

hibernate多对多的更新问题的更多相关文章

  1. hibernate多对多关联映射

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  2. hibernate多对一双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  3. hibernate多对一单向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  4. Hibernate多对一ManytoOne

    ------------------------Hibernate多对一ManytoOne 要点: ManytoOne配置在多端 可以配置级联操作 @ManyToOne(cascade=Cascade ...

  5. Hibernate多对多操作

    ---------------------siwuxie095 Hibernate 多对多操作 以用户和角色为例 (一)多对多映射配置 第一步:创建两个实体类,用户和角色 第二步:让两个实体类之间互相 ...

  6. Hibernate多对多关系映射(建表)

    下边讲述Hibernate多对多关系映射. 多对多关系的表的结构为: 两个实体表,还包含一个关系表,关系表为复合主键,如果要使用Hibernate多对多关系映射,则关系表必须只包含两个字段,如果生成了 ...

  7. atitit.atitit.hb many2one relate hibernate 多对一关联配置..

    atitit.atitit.hb many2one relate hibernate 多对一关联配置.. 1. 多对一单向 @ManyToOne 1 1. 其中@JoinColumn 注解 2 2.  ...

  8. hibernate 多对多

    HibernateHibernate多对多关联映射通常别拆分成两个多对一关联映射1. 下面的HostBean.UserBean.UserHostBean,UserHostBean是两个表之间的关联表, ...

  9. Nhibernate 多对多级联更新

    问题是这样的,有两个表:文章(Article)和分类(Lable),这两者之间的关系是多对多关联,如果你用Nhibernate来保存数据的话非常的好操作,新建Article,然后把Lable值赋值给A ...

随机推荐

  1. 关于getdate()的不同的日期格式

    在使用Sql Server查询数据库时,我们经常会需要查询日期格式的数据,对于日期在sql语言中的格式有一定的要求,通过修改convert中的最后一位参数,可以返回不通格式的时间,具体实现如下: Se ...

  2. 前后端分离djangorestframework——限流频率组件

    频率限制 什么是频率限制 目前我们开发的都是API接口,且是开房的API接口.传给前端来处理的,也就是说,只要有人拿到这个接口,任何人都可以通过这个API接口获取数据,那么像网络爬虫的,请求速度又快, ...

  3. 如何写 go 代码 (How to Write Go Code 翻译)

    目录 1. 写在前面的话 2. 介绍 3. 代码组织 3.1. 工作区 3.2. GOPATH 环境变量 3.3. Package 路径 3.4. 第一个 GO 程序 3.5. 第一个 GO 库 3. ...

  4. May 26. 2018 Week 21st Saturday

    Do what you say, say what you do. 做你说过的,说你能做的. Be honest to yourself, and be honest to those people ...

  5. 使用Java命令行方式导入第三方jar包来运行Java程序的命令

    1.首先使用命令行进入到a.java所在的文件夹:(比如我的在D:\javaeeworkspace\SharedPS_WS\src\com\dyf\main 这样一个路径下,) d: 回车, cd D ...

  6. 原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y

    关于js鼠标事件综合各大浏览器能获取到坐标的属性总共以下五种 event.clientX/Y event.pageX/Y event.offsetX/Y event.layerX/Y event.sc ...

  7. 2293: Distribution Center 中南多校

    Description The factory of the Impractically Complicated Products Corporation has many manufacturing ...

  8. centos7下安装docker(13.4容器volume总结)

    最近我们学习了docker 存储,首先docker存储有两种:storage driver和data volume. storage driver是由镜像层和容器层组成的,可以通过docker ins ...

  9. [转自机器之心] 刚入校门的PhD们还可以抢救一下(读研读博指南)

    本文作者 Lucy A. Taylor 最近博士毕业,取得了牛津大学跨学科生物科学博士学位. 读博是件难事,一路上可能会遇到很多挫折.失败.崩溃时刻.Lucy 多么希望在开始读博时就能收到一些有益的建 ...

  10. [ZJOI2012]网络

    嘟嘟嘟 今天复习lct,趁着还年轻多写点数据结构. 首先不得不吐槽一下,题面好长啊-- 通过观察发现,\(c \leqslant 10\).那么就可以暴力的建10棵lct. 接下来说下具体做法: 1. ...