2010-08-24 15 views
14

Eventuali duplicati:
Hibernate Error: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the sessionHibernate: oggetto diverso con lo stesso valore identificativo è già stato associato alla sessione

quando uso il DAO.update (userbean), session.SaveOrUpdate(e); gettare il Eccezione: l'oggetto diverso con lo stesso valore identificativo era già associato alla sessione

la funzione è come successiva:

public E save(E e) { 
    Session session = null; 
    try { 
     session = sessionFactory.openSession(); 
     log.debug("session="+session.hashCode()+" save "+e); 
     session.SaveOrUpdate(e); //here throws exception 
     session.flush(); 
    } 
    catch (Exception e1) { 
     log.err("Cannot open hibernate session "+ e1.getMessage()+" cause : "+e1.getCause()); 
     e1.printStackTrace(); 
    } 
    finally { if (session != null) session.close(); session = null;} 
    return e ; 
} 

l'userbean è un'istanza di classe UserBean

public class UserBean{ 
    private List<GroupBean> groups = new ArrayList<GroupBean>(); 
    private List<RoleBean> roles = new ArrayList<RoleBean>(); 
} 

public class GroupBean{ 
private List<RoleBean> roles = new ArrayList<RoleBean>(); 
} 

ogni groupbean ha una lista di ruoli, che non sono cambiati.

nel database, di gruppo e ruolo è molti-a-molti mappatura,

per esempio,

abbiamo un groupbean 1 #, è ruoli: rolebean # 1, # 2 rolebean;

groupbean # 2, quali ruoli sono rolebean # 1.

ora creare una nuova userbean 1 #, è gruppi è groupbean # 1 e se voglio aggiungere la rolebean # 1 a userbean 1 #, lo farà genera l'eccezione come il titolo descript

mi guardo il server.log, e trovare che quando ho DAO.save utente, l'ordine è saveOrUpdate:

userbean#1 
|---|-----------***userbean.groups 
|  |  groupbean#1 
|  |   groupbean.roles 
|  |    rolebean#1 # save relebean#1 the first time 
|  |    ---done rolebean#1 
|  |   ------done all rolebeans of group.roles 
|  |  ---done groupbean#1 
|  |-----------done all groupbeans of userbean.groups 
|---|-----------***userbean.roles 
    |  rolebean#1   # save rolebean#1 the second time, and throws exception here! 
    |  ----done rolebean#1 
    |  ..... 
    |-----------done all rolebeans of userbean.roles 

la causa dell'eccezione è rolebean 1 # è stato salvato due volte in una sessione, e la loro identità è la stessa .

Nella funzione di salvataggio (E e), Se uso

session.merge(e); 

sostituire

session.SaveOrUpdate(e); 

non gettare un'eccezione, ma la rolebean # 1 non è assocaited a userbean # 1

chiunque può dare qualche suggerimento su questo?

risposta

27

Sarebbe più facile identificare la causa esatta se è possibile vedere il codice in cui si assegna il bean di ruolo sia all'utente che al gruppo.

In generale, ciò che l'eccezione ci dice è che ci sono due versioni di quel bean di ruolo (due istanze). Il primo viene aggiornato, quindi Hibernate colpisce il secondo e riconosce che si tratta dello stesso identificatore ma di una diversa versione separata del ruolo.

Hibernate non è sicuro di quale sia corretto, e in saveOrUpdate, genera un'eccezione per farvi sapere.

Il contratto di Merge funziona in modo diverso, nel senso che supporterà che l'utente intende salvarlo di nuovo (ad es., unire tutte le mie modifiche), quindi ricollegherà la seconda versione, unirà tutte le modifiche e salverà qualsiasi aggiornamento.

Ho bloggato circa SaveOrUpdate vs Merge con qualche dettaglio in più per spiegare cosa sta succedendo.

Se si desidera mantenere SaveOrUpdate, è necessario capire cosa si sta facendo nel compito che causa l'assegnazione di una diversa istanza del ruolo alla raccolta di ruoli dell'utente rispetto ai gruppi.

Altrimenti, se gli effetti di unione funzionano per te (che è in linea con lo standard JPA), quindi utilizzarlo.

Problemi correlati