错误原因

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. [20190214]11g Query Result Cache RC Latches.txt

    [20190214]11g Query Result Cache RC Latches.txt --//昨天我重复链接http://www.pythian.com/blog/oracle-11g-qu ...

  2. linux shell 指令 诸如-d, -f, -e之类的判断表达式简介

    一.文件比较运算符 1. e filename 如果 filename存在,则为真 如: [ -e /var/log/syslog ] 2. -d filename 如果 filename为目录,则为 ...

  3. 第六章 第一个Linux驱动程序: 统计单词个数

    一.编写Linux驱动程序的步骤 第1 步:建立Linux 驱动骨架(装载和卸载Linux 驱动) 骨架部分主要是Linux驱动的初始化和退出函数,代码如下: #include <linux/m ...

  4. 团队作业——UML设计

    Deadline:2017-10-29 20:00(课堂作业) 导言 同学们已经做了需求的分析,也做了详细的系统设计,画过了一些小小的类图/用例图,对自己要做什么应该有比较清晰的认识了.接下来,我们要 ...

  5. Python中进程线程协程小结

    进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...

  6. Spring的AOP开发入门,Spring整合Junit单元测试(基于ASpectJ的XML方式)

    参考自 https://www.cnblogs.com/ltfxy/p/9882430.html 创建web项目,引入jar包 除了基本的6个Spring开发的jar包外,还要引入aop开发相关的四个 ...

  7. 《Java大学教程》--第1章 步入Java世界

    1.2 软件:用于计算机执行的指令的集合称之为程序(program).单个程序或者一组程序称之为软件(software)1.3 编译:计算机的语言称为机器码(machine code).用编译器(co ...

  8. 02.Python网络爬虫第二弹《http和https协议》

    一.HTTP协议 1.官方概念: HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文 ...

  9. keepalived 安装篇-个人实践-编译安装

    官网地址:http://www.keepalived.org/官网文档:http://www.keepalived.org/documentation.html Keepalived的作用是检测服务器 ...

  10. linux中如何查看进程的启动时间

    ps -p PID -o lstart 其中PID是进程的pid [root@lvs-a logs]# -o lstart STARTED Tue Oct ::