hibernate NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
Asked Answered
D

5

14

My Code:

I am trying to do either update/insert. It gets inserted properly, only problem is when I try to update it gives below error message.

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

Error:

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)        

EDIT 2:

I have used

session.merge(accountDetails)

there is no error, but it always does insert data into db instead of update.

Dubois answered 22/9, 2014 at 23:36 Comment(3)
Why are you using two different sessions? You can deal with save and update in same session, unless I am missing something. See if this helps tech.lalitbhatt.net/2014/07/…Ritualize
@lalit, I tried with same session, as I informed, it works fine for insert for the first time, then next step is update, it throws same error. Earlier I was getting stale object state exception, so I used different session. Updated above.Dubois
Possible duplicate of Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the sessionNebiim
D
4
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";
    }

Removed @GeneratedValue from my dto, since value was coming from UI.

Here is the good article, how to use MERGE/UPDATE

Dubois answered 25/9, 2014 at 18:57 Comment(1)
link to artricle is deadUpthrust
C
7

I had this error when opening two sessions. One session for a User and another session for an object that has its primary key a foreign key from User. With this,the two session has the same primary key or identifier. I solved this by session.clear before session.update(type).

public T update(T type) {
        Session session = getSession();
        session.clear();
        session.update( type );
        session.flush();
        return type;
    }
Colcannon answered 28/1, 2016 at 2:46 Comment(0)
D
4
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";
    }

Removed @GeneratedValue from my dto, since value was coming from UI.

Here is the good article, how to use MERGE/UPDATE

Dubois answered 25/9, 2014 at 18:57 Comment(1)
link to artricle is deadUpthrust
S
3

Try using one session only as suggested by lalit.

The code reduced to as below.

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";
}
Suspect answered 23/9, 2014 at 3:7 Comment(1)
I tried with same session, as I informed, it works fine for insert for the first time, then next step is update, it throws same error. Earlier I was getting stale object state exception, so I used different session.Dubois
R
1

Quite late reply but others who are searching for the same error can know. This worked for me. When you are saving data in a loop before commit use session.flush() and after commit use session.clear().

    session.flush();
    session.beginTransaction().commit();
    session.clear();
Robalo answered 24/3, 2015 at 13:20 Comment(0)
G
0

What's the PK of your Account Details entity ? is it AccountsId ?

You've fetched Accounts details from database to your current hibernate session.

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

When you are saving

    session.save(accountDetails);

accountDetails pass from transient state to persisted state, and then managed by current session, but you've already have an object with same ID in your session due to accounts details fetching before, so hibernate session got confused.

When you are using merge, hibernate will synchronize the states of existing in-session object with your new object which is accountDetails.

Gunpoint answered 6/11, 2020 at 12:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.