2014-09-22 6 views
11

My Code:hibernate NonUniqueObjectException: un oggetto diverso con lo stesso valore identificativo è già stato associato alla sessione:

che sto cercando di fare sia l'aggiornamento/inserimento. Si inserisce correttamente, solo il problema è quando cerco di aggiornarlo dà sotto il messaggio di errore.

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

Errore:

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:

ho usato

session.merge(accountDetails)

non v'è alcun errore, ma non sempre inserire i dati in db, invece di aggiornamento.

+2

Perché stai utilizzando due sessioni diverse? Puoi occuparti di salvare e aggiornare nella stessa sessione, a meno che non mi manchi qualcosa. Vedi se questo aiuta http://tech.lalitbhatt.net/2014/07/hibernate-persistent-context-and-session.html – lalit

+0

@lalit, ho provato con la stessa sessione, come ho informato, funziona bene per l'inserimento per il la prima volta, quindi il prossimo passo è aggiornato, genera lo stesso errore. In precedenza stavo ottenendo un'eccezione di stato dell'oggetto scaduto, quindi ho usato una sessione diversa. Aggiornato sopra. – TechFind

risposta

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

Rimosso @GeneratedValue dal mio dto, dal momento che il valore veniva da UI.

Ecco il buon articolo, come utilizzare MERGE/UPDATE

+0

collegamento a artricle è morto – Macilias

4

Provare a utilizzare una sola sessione come suggerito da lalit.

Il codice ridotto a come indicato di seguito.

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

Ho provato con la stessa sessione, come ho informato, funziona bene per l'inserimento per la prima volta, quindi il prossimo passo è l'aggiornamento, genera lo stesso errore. In precedenza stavo ottenendo un'eccezione di stato dell'oggetto scaduto, quindi ho usato una sessione diversa. – TechFind

1

Piuttosto ritardo di risposta, ma gli altri che sono alla ricerca per lo stesso errore può sapere. Questo ha funzionato per me. Quando si salvano i dati in un loop prima di utilizzare commit session.flush() e dopo il commit, utilizzare session.clear().

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

Ho avuto questo errore durante l'apertura di due sessioni. Una sessione per un utente e un'altra sessione per un oggetto che ha la chiave primaria una chiave esterna dell'utente. Con questo, la sessione due ha la stessa chiave primaria o identificatore. Ho risolto questo problema con session.clear prima di session.update (type).

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