web-dev-qa-db-ja.com

hibernate NonUniqueObjectException:同じ識別子値を持つ別のオブジェクトがすでにセッションに関連付けられていました:

私のコード:

更新/挿入のいずれかを実行しようとしています。正しく挿入されますが、更新しようとするとエラーメッセージが表示されるだけです。

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)

エラーはありませんが、更新の代わりに常にデータベースにデータを挿入します。

11
TechFind
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";
    }

値がUIから取得されていたため、@ GeneratedValueをdtoから削除しました。

ここに良い記事、使用方法があります MERGE/UPDATE

5
TechFind

2つのセッションを開くときにこのエラーが発生しました。ユーザーの1つのセッションと、その主キーがユーザーからの外部キーであるオブジェクトの別のセッション。これにより、2つのセッションは同じ主キーまたは識別子を持ちます。 session.update(type)の前にsession.clearでこれを解決しました。

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

6
kent

Lalitの提案に従って、1つのセッションのみを使用してみてください。

コードは以下のようになりました。

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";
}
4
Ankur Singhal

かなり遅い返信ですが、同じエラーを検索している他の人は知ることができます。これは私のために働いた。コミット前にループでデータを保存する場合は、session.flush()を使用し、コミット後にsession.clear()を使用します。

    session.flush();
    session.beginTransaction().commit();
    session.clear();
1
Pawan Pareek