Una de las cosas buenas que nos ha traído JEE y el uso de JPA es el manejo de las transacciones. Como se gestionan ahora a través del software y como se puede persistir o revertir datos fácilmente.
Pero se puede dar el caso que por motivos concretos queremos evitar que se realice un rollback de la operación si algo falla en la misma. El ejemplo típico puede ser porque dentro del propio service, envías un correo tras persistir los datos. Aún en el caso que hubiese un error con el servidor de correo, no querrías que se volviese atrás en la operación de BBDD. Para eso haríamos uso de 'noRollbackFor' o de 'dontRollbackOn' en función de la anotación @Transactional que estemos usando (Si es la propia de JEE o de Spring).
//org.springframework.transaction.annotation.Transactional @Transactional( noRollbackFor = { MessagingException.class } ) public void createUser( final User user ) { //... } //javax.transaction.Transactional @Transactional( dontRollbackOn = { MessagingException.class } ) public void createUser( final User user ) { //... }
Pero debemos tener en cuenta que esta propiedad solo nos funciona con operaciones de tipo read-only. Por lo que llegamos al meollo de este post. Como podemos evitar que haga rollback en una operación que no es de tipo read-only, ya que en dicho caso no nos valdrán las propiedades anteriormente comentadas.
Para lograrlo haremos uso de la anotación de Spring y su propiedad 'propagation'. Esta propiedad es la que nos indicará cual es el comportamiento de las transacciones. Por defecto tiene el valor 'REQUIRED', y permite que los métodos continúen la transacción del método superior o creen una, en caso de que no exista.
Para solucionar nuestro problema deberemos indicarle a dicha propiedad el valor 'REQUIRES_NEW'. De esta forma, se creará un transacción específica para el método y en caso de error, evitará su propagación a métodos superiores. Quedando el código de la siguiente forma:
Para lograrlo haremos uso de la anotación de Spring y su propiedad 'propagation'. Esta propiedad es la que nos indicará cual es el comportamiento de las transacciones. Por defecto tiene el valor 'REQUIRED', y permite que los métodos continúen la transacción del método superior o creen una, en caso de que no exista.
Para solucionar nuestro problema deberemos indicarle a dicha propiedad el valor 'REQUIRES_NEW'. De esta forma, se creará un transacción específica para el método y en caso de error, evitará su propagación a métodos superiores. Quedando el código de la siguiente forma:
@Transactional( propagation = Propagation.REQUIRES_NEW, noRollbackFor = { MessagingException.class } ) public void createUser( final User user ) { dao.save(user); emailService.sendCreationUserMail(user); }
No hay comentarios:
Publicar un comentario