2012-02-24 14 views
6

Hola Tengo un DAO simple con la función siguiente.JPA EntityManager persist() provocando que el objeto aparezca separado aunque se produjo un error

public element createElement(Element e){ 

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

    return e; 
} 

La mesa entidad tiene una restricción única en el par (tipo, valor) y tengo una prueba a continuación:

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

Mi primer error atrapado ocurre como espero ya que sé que estoy m violar la restricción, el segundo try/catch no debería generar un error en lo que a mí respecta, pero lo hace, lo que consigo su presente:

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

por lo que parece llamar a persistir() sobre " e "aunque no fue persistente tiene Hibernate causado para pensar que es una entidad separada.

Esto es molesto porque estas funciones están siendo utilizadas por una interfaz JSF que trata con la excepción ConstraintViolation, pero aferrándose deliberadamente al objeto para que el usuario pueda cambiar uno de los campos y vuelva a intentarlo, y obtienen el error de entidad separada.

¿Este comportamiento es un error de hibernación porque no creo que debería estar haciendo esto realmente? ¿Hay una forma de evitar esto en el nivel DAO para que persista no logre tratar mi objeto como separado si no persiste realmente?

Saludos,

Glen x

+0

Solo para sonrisas, ¿qué ocurre si creas un nuevo elemento y configuras los valores adecuados antes del último createElement al que llamas? –

+0

Va bien. – Link19

+0

¿Eso ayuda? Si no, esto puede funcionar ... e.setValue (1); e = dao.createElement (e); (<- fallará) pero luego e.setValue (2); edao.createElement (e); (<- Funcionará, con suerte). –

Respuesta

3

Una excepción lanzada por Hibernate no es recuperable. Lo único que debe hacer cuando ocurre una excepción es deshacer la transacción y cerrar la sesión. El estado de la sesión (y sus entidades) después de dicha excepción es inestable.

Si desea mantener intacta una copia del elemento, utilice merge() en lugar de persist(), o clone el elemento antes de conservarlo.

Tenga en cuenta que se espera la excepción, ya que cuando Hibernate persiste y vacía la entidad, comienza generando un ID y asignando el ID a la entidad, luego inserta la fila, lo que causa la excepción. Entonces, después de la excepción, la entidad tiene una ID asignada, y Hibernate lo considera como una entidad separada. Podría intentar restablecer el ID a nulo y ver si funciona, pero preferiría clonar la entidad antes o usar merge.

Cuestiones relacionadas