【问题标题】:hibernate NonUniqueObjectException: a different object with the same identifier value was already associated with the session:hibernate NonUniqueObjectException:具有相同标识符值的不同对象已与会话关联:
【发布时间】:2014-11-17 01:02:44
【问题描述】:

我的代码:

我正在尝试更新/插入。它被正确插入,唯一的问题是当我尝试更新它时,它会给出以下错误消息。

private String sessionType=null;
public String getAccountsDetails(List<Account> accountList) {       
    Session session = sessionFactory.openSession();
    for (Account account : accountList) {
        AccountDetails accountDetails = new AccountDetails();
        accountDetails.setAccountsId(Long.parseLong(account.getId()));
        accountDetails.setAccounttype(account.getAccountType().value());
        Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
        List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
        if(queryList.size()>0){         
            session.update(accountDetails);
        }else{
            session.save(accountDetails);
        }
    }
    session.flush();  
    session.beginTransaction().commit();
    session.clear();
    session.close();           
    return "Successfully data updated into table";
}

错误:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.trinet.mulesoft.quickbooks.dto.AccountDetails#0]
    at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:638)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:305)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:246)        

编辑 2:

我用过

session.merge(accountDetails)

没有错误,但它总是将数据插入数据库而不是更新。

【问题讨论】:

标签: hibernate hibernate-mapping


【解决方案1】:

尝试仅按照 lalit 的建议使用一个会话。

代码简化如下。

private String sessionType=null;
public String getAccountsDetails(List<Account> accountList) {       
    Session session = sessionFactory.openSession();

    for (Account account : accountList) {
        AccountDetails accountDetails = new AccountDetails();
        accountDetails.setAccountsId(Long.parseLong(account.getId()));
        accountDetails.setAccounttype(account.getAccountType().value());
        Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
        List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
        if(queryList.size()>0){         
            session.update(accountDetails);
            sessionType = "update";
        }else{
            session.save(accountDetails);
            sessionType = "save";
        }
    }
        session.flush();  
        session.beginTransaction().commit();
        session.clear();
        session.close();


    return "Successfully data updated into table";
}

【讨论】:

  • 我尝试了相同的会话,正如我所告知的,它第一次插入时效果很好,然后下一步是更新,它会抛出同样的错误。早些时候我遇到过时的对象状态异常,所以我使用了不同的会话。
【解决方案2】:
public String getAccountsDetails(AccountDetails accountDetails) {
        System.out.println("accountDetails.accoundId-->"+accountDetails.getAccountsId());
        Session session = sessionFactory.openSession();
        Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
        List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
        session.close();
        Session session2 = sessionFactory.openSession();
//          session.saveOrUpdate(accountDetails);
        try{
            if(queryList.size()>0){                 
                session2.beginTransaction();
                /*
                 *  comment below line-50,51 to use update instead of merge, and uncomment line 53
                 */
                AccountDetails acDet = (AccountDetails) session2.get(AccountDetails.class, new Long(1));//line 50
                session2.merge(accountDetails);//line 51
                System.out.println("acDet-->"+acDet+"  --accountDetails->  "+accountDetails);//line 52
//              session2.update(accountDetails);//line 53
            }else{
                session2.beginTransaction();
                session2.save(accountDetails);
            }
        }catch(DIRException e){
            session2.getTransaction().rollback();
            System.out.println("Getting Exception : " + e.getLocalizedMessage());
        }finally{
             session2.getTransaction().commit();
             session2.close();
        }
        return "Successfully data updated into table";
    }

从我的 dto 中删除了@GeneratedValue,因为值来自 UI。

这里是好文章,如何使用MERGE/UPDATE

【讨论】:

  • 文章链接失效
【解决方案3】:

回复很晚,但搜索相同错误的其他人可以知道。这对我有用。当您在提交之前使用 session.flush() 并在提交之后使用 session.clear() 在循环中保存数据时。

    session.flush();
    session.beginTransaction().commit();
    session.clear();

【讨论】:

    【解决方案4】:

    我在打开两个会话时遇到了这个错误。 一个用户会话和一个对象的另一个会话,该对象的主键是来自用户的外键。 这样,两个会话具有相同的主键或标识符。 我在 session.update(type) 之前通过 session.clear 解决了这个问题。

    public T update(T type) {
            Session session = getSession();
            session.clear();
            session.update( type );
            session.flush();
            return type;
        }
    

    【讨论】:

      【解决方案5】:

      您的 Account Details 实体的 PK 是什么?是 AccountsId 吗?

      您已从数据库中获取帐户详细信息到您当前的休眠会话。

          Query query = session.createQuery("from QBAccounts qba where qba.accountsId=:accId");
          List<AccountDetails> queryList = query.setParameter("accId", accountDetails.getAccountsId()).list();
      

      保存时

          session.save(accountDetails);
      

      accountDetails 从瞬时状态传递到持久状态,然后由当前会话管理,但是由于之前获取帐户详细信息,您的会话中已经有一个具有相同 ID 的对象,所以休眠会话被混淆了。

      当您使用合并时,hibernate 会将现有会话中对象的状态与您的新对象(即 accountDetails)同步。

      【讨论】:

        猜你喜欢
        • 2018-03-26
        • 1970-01-01
        • 1970-01-01
        • 2019-07-27
        • 1970-01-01
        • 2011-01-09
        • 2011-03-16
        • 1970-01-01
        相关资源
        最近更新 更多