hibernate多对多的更新问题
错误原因
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多对多的更新问题的更多相关文章
- hibernate多对多关联映射
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- hibernate多对一单向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- Hibernate多对一ManytoOne
------------------------Hibernate多对一ManytoOne 要点: ManytoOne配置在多端 可以配置级联操作 @ManyToOne(cascade=Cascade ...
- Hibernate多对多操作
---------------------siwuxie095 Hibernate 多对多操作 以用户和角色为例 (一)多对多映射配置 第一步:创建两个实体类,用户和角色 第二步:让两个实体类之间互相 ...
- Hibernate多对多关系映射(建表)
下边讲述Hibernate多对多关系映射. 多对多关系的表的结构为: 两个实体表,还包含一个关系表,关系表为复合主键,如果要使用Hibernate多对多关系映射,则关系表必须只包含两个字段,如果生成了 ...
- atitit.atitit.hb many2one relate hibernate 多对一关联配置..
atitit.atitit.hb many2one relate hibernate 多对一关联配置.. 1. 多对一单向 @ManyToOne 1 1. 其中@JoinColumn 注解 2 2. ...
- hibernate 多对多
HibernateHibernate多对多关联映射通常别拆分成两个多对一关联映射1. 下面的HostBean.UserBean.UserHostBean,UserHostBean是两个表之间的关联表, ...
- Nhibernate 多对多级联更新
问题是这样的,有两个表:文章(Article)和分类(Lable),这两者之间的关系是多对多关联,如果你用Nhibernate来保存数据的话非常的好操作,新建Article,然后把Lable值赋值给A ...
随机推荐
- JAVA多线程的问题以及处理(一)【转】
多线程编程为程序开发带来了很多的方便,但是也带来了一些问题,这些问题是在程序开发过程中必须进行处理的问题. 这些问题的核心是,如果多个线程同时访问一个资源,例如变量.文件等,时如何保证访问安全的问题. ...
- Python平时代码的一些知识
os.walk的作用: def file_name(file_dir): for root, dirs, files in os.walk(file_dir): print(root) #当前目录 ...
- AngularJS学习之旅—AngularJS 表达式(二)
1.AngularJS 表达式 AngularJS 表达式写在双大括号内:{{ expression }}. AngularJS 表达式把数据绑定到 HTML,这与 ng-bind 指令有异曲同工之妙 ...
- python 中文报错
解决的办法为:在程序的开头写入如下代码,这就是中文注释 #coding=utf-8
- Cisco 日常巡检命令
https://www.cnblogs.com/qzqdy/p/8116903.html 日常排错命令6 交换机的前面板有几个指示灯,用于监控系统的活动和性能.这些指示灯称之为发二极管(LED) 1. ...
- 使用concurrent.futures模块中的线程池与进程池
使用concurrent.futures模块中的线程池与进程池 线程池与进程池 以线程池举例,系统使用多线程方式运行时,会产生大量的线程创建与销毁,创建与销毁必定会带来一定的消耗,甚至导致系统资源的崩 ...
- 对Can We MakeOperating SystemsReliable and Secure 的翻译
摘要:微内核-相对于大内核(monolithic kernels)来说,由于它的 lower performance,长期以来被认为是不可接受的.而现在,由于它潜 在的高可靠性(higher reli ...
- 【PAT】B1012 数字分类
注意逻辑的描述,只要认真看题,就能做对,如果自己结果一直不正确,请仔细推一下样例结果 #include<stdio.h> int arr[1005]; int main(){ int N, ...
- ASP.NET -- WebForm -- 给图片添加水印标记
ASP.NET -- WebForm: 给图片添加水印标记 ASP.NET:使用 WebForm(C#) 制作一个简单的为图片添加水印的页面. 1. Test2.aspx文件 <%@ Page ...
- Java入门(七):方法
方法,在日常生活中可以理解成解决问题或处理事情的技巧,一个方法的形成,需要思考和分析,从而形成一步一步的步骤,最后在实际执行过程中验证自己的思路.在Java中,方法的形成亦是如此. 方法,指用于封装一 ...