2011-02-04 27 views
11

Actualmente estoy trabajando con @PostPersist y @PostUpdate, y en esos desencadenantes estoy persistiendo entidades adicionales. La pregunta es, ¿esos factores desencadenantes en la misma transacción y si no es posible forzarlo?JPA/@PostPersist @PostUpdate - transaction

Para mí funciona de esta manera. Mientras estaba revisando los registros, la transacción no existe (está comprometida justo antes de que se inicie el activador) lo que me impide (sin REQUIRES_NEW en el método persistente del bean inyectado) guardar las entidades adicionales en la base de datos. REQUIRED El atributo se ignora por completo, y el atributo MANDATORY no arroja una excepción.

¿Puede ser el problema con JUnit (ya que estoy en la fase de desarrollo y no probé el comportamiento en el env total)?

Si no es posible extender la transacción en este disparador, cómo asegurarse de que si la reversión se produce antes del @PostPersist y @PostUpdate, esas operaciones también se revertirán.

Gracias de antemano por cualquier ayuda,

Saludos cordiales, P.

+0

hey. cuando realizo las pruebas, veo que todas las operaciones en el oyente están en la misma transacción de la operación maestra. Uso la anotación @PostUpdate para marcar al oyente. – Scarlett

Respuesta

11

El disparo de un evento PostPersist no indica que la entidad ha hecho cometer un éxito. La transacción puede revertirse después de la activación del evento, pero antes de la confirmación exitosa. Si en el PostPersist obtener el gestor de entidades utilizada en la operación y luego hacer somehting así:

@PostPersist 
void someMethod() { 
    EntityManager em = null; 
    em = getEntityManagerUsedInTransaction(); 
    EntityTransaction et = em.getTransaction(); // should return the current transaction 
    if (et.isActive()) { 
    // do more db stuff 
    } 
} 

NB: No he probado esto por lo que es sólo una especulación (aunque' He utilizado el gatillo vida evento extensivamente para otras cosas). Debo agregar que no creo que sea una buena idea. Use PostPersist para marcar que otras entidades deben persistir y hacerlo en otra transacción.

10

Si está utilizando la primavera siempre se puede registrar un TransactionSynchronization con el administrador de transacción actual para ser llamado de nuevo en eventos tales como cometa de la transacción actualmente en ejecución:

@PostPersist 
void onPersist() { 
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { 

     @Override 
     public void beforeCommit(boolean readOnly) { 
     // do work 
     } 
    }); 
    }  
} 

Un TransactionSynchronization también proporciona servicios repetidos después de una la transacción se ha comprometido con éxito y antes/después de que se complete una transacción.

Si hay que fijarse en si la transacción se haya cometido o se deshace, utilice afterCompletion(int status).

Para detalles, eche un vistazo a TransactionSynchronization's JavaDoc.

-1

JPA métodos de devolución de llamada internas métodos de devolución de llamada internos son los métodos que se definen dentro de una clase de entidad. Por ejemplo, la siguiente clase de entidad define todos los métodos de devolución de llamada compatibles con las implementaciones vacías:

@Entity 
public static class MyEntityWithCallbacks { 
    @PrePersist void onPrePersist() {} 
    @PostPersist void onPostPersist() {} 
    @PostLoad void onPostLoad() {} 
    @PreUpdate void onPreUpdate() {} 
    @PostUpdate void onPostUpdate() {} 
    @PreRemove void onPreRemove() {} 
    @PostRemove void onPostRemove() {} 
} 

métodos de devolución de llamada internos siempre deben devolver nulo y no tienen argumentos. Pueden tener cualquier nombre y cualquier nivel de acceso (público, protegido, paquete y privado) pero no deben ser estáticos.

La anotación especifica cuando se invoca el método de devolución de llamada:

clase
@PrePersist - before a new entity is persisted (added to the EntityManager). 
@PostPersist - after storing a new entity in the database (during commit or flush). 
@PostLoad - after an entity has been retrieved from the database. 
@PreUpdate - when an entity is identified as modified by the EntityManager. 
@PostUpdate - after updating an entity in the database (during commit or flush). 
@PreRemove - when an entity is marked for removal in the EntityManager. 
@PostRemove - after deleting an entity from the database (during commit or flush). 

Una entidad puede incluir métodos de devolución de llamada para cualquier subconjunto o combinación de eventos del ciclo de vida pero no más de un método de devolución de llamada para el mismo evento. Sin embargo, el mismo método se puede usar para múltiples eventos de devolución de llamada marcándolo con más de una anotación.

De forma predeterminada, un método de devolución de llamada en una clase super entidad también se invoca para los objetos de entidad de las subclases a menos que la subclase anule ese método de devolución de llamada. Para evitar conflictos con la operación de base de datos original que dispara el evento del ciclo de vida de la entidad (que aún está en curso) los métodos de devolución de llamada no deben llamar a EntityManager o métodos de consulta y no deben acceder a ningún otro objeto de entidad.

Si un método de devolución de llamada arroja una excepción dentro de una transacción activa, la transacción se marca para la reversión y no se invocan más métodos de devolución de llamada para esa operación.

Cuestiones relacionadas