错误原因

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. Spring(mvc)思维导图

    spring mvc简介与运行原理 Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器 ...

  2. jquery hover事件只触发一次动画

    最近工作时遇到个关于动画的问题,如下: $("div").hover( function() { $(this).animate({"margin-top":& ...

  3. 洗礼灵魂,修炼python(64)--爬虫篇—re模块/正则表达式(2)

    前面学习了元家军以及其他的字符匹配方法,那得会用啊对吧?本篇博文就简单的解析怎么运用 正则表达式使用 前面说了正则表达式的知识点,本篇博文就是针对常用的正则表达式进行举例解析.相信你知道要用正则表达式 ...

  4. 关于JBoss -“Closing a connection for you,please close them yourself”

    使用JNDI的方式从Jboss里获取数据连接(Connection)的方式,Jboss会管理connection,不需要自己手动去关闭,但Jboss老是提示需要自己来关闭connection,针对Jb ...

  5. PostgreSQL 表值函数

    方法1create type deptSon as ( mid ), id ), name ), DeptParentId ) ); CREATE OR REPLACE FUNCTION functi ...

  6. intellij IDEA导入java源码

    第一步: 从安装的jdk目录中找到src.zip文件, 这里是java源码的压缩包 第二步: 打开IDEA, 随便一个java相关项目,打开右上角的project structure 第三步: 点开源 ...

  7. ESLint笔记

    ESLint是JavaScript的代码检查工具.因为JS是弱类型的语言,不需要编译,代码错误是在运行时调适的,所以需要个工具在编码的过程发现问题.ESLint的初衷是为了让程序员可以创建自己的检测规 ...

  8. spring的工厂类

    主要介绍两种工厂接口BeanFactory(老版本,已过时)和ApplicationContext ApplicationContext接口:每次在加载applicationContext.xml的时 ...

  9. ubuntu下配置rsync,实现远程备份

    rysnc(remote synchronize)在CentOS系统默认安装在/usr/bin,此外rysnc在windows平台下也有相应版本.主页地址为: http://rsync.samba.o ...

  10. GraphQL 是什么

    我的理解,GraphQL 是一种以Json为载体实现:操作数据和获取结果的需求的查询语言!简言:以Json换Json.