web-dev-qa-db-fra.com

hibernate NonUniqueObjectException: un objet différent avec la même valeur d'identifiant était déjà associé à la session:

Mon code:

J'essaie de faire une mise à jour/insertion. Il est inséré correctement, le seul problème est lorsque j'essaie de le mettre à jour, il donne un message d'erreur ci-dessous.

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

Erreur:

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:

J'ai utilisé

session.merge (accountDetails)

il n'y a pas d'erreur, mais il insère toujours des données dans db au lieu de mettre à jour.

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

Suppression de @GeneratedValue de mon dto, car la valeur provenait de l'interface utilisateur.

Voici le bon article, comment utiliser MERGE/UPDATE

5
TechFind

J'ai eu cette erreur lors de l'ouverture de deux sessions. Une session pour un utilisateur et une autre session pour un objet dont la clé primaire est une clé étrangère de l'utilisateur. Avec cela, les deux sessions ont la même clé primaire ou identifiant. J'ai résolu cela par session.clear avant session.update (type).

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

6
kent

Essayez d'utiliser une seule session comme suggéré par lalit.

Le code a été réduit comme ci-dessous.

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

Réponse assez tardive mais ceux qui recherchent la même erreur peuvent le savoir. Cela a fonctionné pour moi. Lorsque vous enregistrez des données dans une boucle avant la validation, utilisez session.flush () et après la validation, utilisez session.clear ().

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