2012-02-24 15 views
6

Ciao Ho un semplice DAO con la funzione di seguito.JPA EntityManager persist() che fa apparire l'oggetto distaccato anche se è stato generato un errore

public element createElement(Element e){ 

    em.persist(e); 
    em.flush(); 

    return e; 
} 

La tabella entità ha un vincolo univoco sulla coppia (tipo, il valore) e ho un test di seguito:

public void testCreateElement() throws DataAccessException { 
     // Start with empty Element table 

     Element e = new Element(); 
     e.setType(myType.OTHER); 
     e.setValue("1"); 
     dao.createElement(e); 

     e = new Element(); 
     e.setType(MyType.OTHER); 
     e.setValue("1"); 
     try{ 
       // this should violate unique constraint of database. 
       dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 

     e.setValue("2"); 
     try{ 
      // I expect this to work as there is no element with these values. 
      dao.createElement(e); 
     } catch (Exception ex) { 
      System.out.println(ex); 
     } 
    } 

Il mio primo errore catturato accade come mi aspetto da quando so che ho' m violando il vincolo, la seconda try/catch non dovrebbe genera un errore per quanto mi riguarda, ma lo fa, che cosa ottengo il suo presente:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mypackage.Element 

così sembra chiamare persistono() su " e "anche se non è stato persistito ha ha causato l'ibernazione di pensare che sia un'entità distaccata.

Questo è fastidioso perché queste funzioni vengono utilizzate da un front-end JSF che si occupa dell'eccezione ConstraintViolation, ma che si aggrappano deliberatamente all'oggetto in modo che l'utente possa modificare uno dei campi e riprovare, e ottengono l'errore dell'entità distaccata.

Questo comportamento è un errore di ibernazione perché non penso che dovrebbe farlo davvero? C'è un modo per aggirare questo a livello di DAO in modo tale che persista vinto; t trattare il mio oggetto come distaccato se non è effettivamente persistente?

saluti,

Glen x

+0

Solo per i sorrisi, cosa succede se si crea un nuovo elemento e si impostano i valori corretti prima dell'ultimo createElement che si sta chiamando? –

+0

Va bene. – Link19

+0

Questo aiuto? In caso contrario, potrebbe funzionare ... e.setValue (1); e = dao.createElement (e); (<- fallirà) ma poi e.setValue (2); edao.createElement (e); (<- funzionerà, si spera). –

risposta

3

Un'eccezione lanciata da Hibernate non è recuperabile. L'unica cosa che dovresti fare quando si verifica un'eccezione è il rollback della transazione e chiudere la sessione. Lo stato della sessione (e le sue entità) dopo tale eccezione è instabile.

Se si desidera mantenere una copia dell'elemento non toccata, utilizzare merge() anziché persist() o clonare l'elemento prima di mantenerlo.

Si noti che l'eccezione è prevista, poiché quando Hibernate persiste e svuota l'entità, inizia generando un ID e assegnando l'ID all'entità, quindi inserisce la riga, che causa l'eccezione. Quindi, dopo l'eccezione, l'entità ha un ID assegnato, ed è quindi considerata come un'entità indipendente da Hibernate. Potresti provare a reimpostare l'ID su null e vedere se funziona, ma preferirei clonare l'entità prima o usare l'unione.