zoukankan      html  css  js  c++  java
  • hibernate多对多的更新问题

    错误原因

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

    大意可以理解成在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#2]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#2]] with root cause
    org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.dabai.pojo.Privilege#2]
        at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:648)
        at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
        at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:227)
        at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
        at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:73)
        at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:648)
        at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:640)
        at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:218)
        at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398)
        at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
        at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
        at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:431)
        at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:363)
        at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
        at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
        at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
        at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:150)
        at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:141)
        at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:74)
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
        at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
        at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
        at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
        at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
        at org.springframework.orm.hibernate5.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:581)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
        at com.sun.proxy.$Proxy46.editRole(Unknown Source)
  • 相关阅读:
    Maximum Depth of Binary Tree
    Single Number
    Merge Two Sorted Lists
    Remove Nth Node From End of List
    Remove Element
    Remove Duplicates from Sorted List
    Add Two Numbers
    编译视频直播点播平台EasyDSS数据排序使用Go 语言 slice 类型排序的实现介绍
    RTMP协议视频直播点播平台EasyDSS在Linux系统中以服务启动报错can’t evaluate field RootPath in type*struct排查
    【解决方案】5G时代RTMP推流服务器/互联网直播点播平台EasyDSS实现360°全景摄像机VR直播
  • 原文地址:https://www.cnblogs.com/notably/p/10571546.html
Copyright © 2011-2022 走看看