java - example - spring transaction propagation
Interceptar la transacción solo cuando esté comprometido, pero antes se haya comprometido (2)
El contexto es Java - JPA con Hibernate y Spring.
Tomemos el escenario del protocolo de confirmación en dos fases (pero solo con un recurso):
Consulta para comprometerse desde la aplicación
Vote Sí / No (de la base de datos en nuestro caso)
3.1. Si es así desde la base de datos
3.1.1. ( Hacer devolución de llamada en el código ) - no forma parte del protocolo
3.1.2. Comprométete con la base
3.2 Si no
3.2.1 Revertir a la base de datos
Lo que quiero es una forma de hacer la devolución de llamada desde 3.1.1 en el código, pero solo cuando se sabe que la transacción se confirmará, pero antes se ha comprometido. Además, si se lanza una excepción aquí, entonces la transacción se debe revertir.
Usar TransactionSynchronization
(*) desde Spring, le permite interceptar una transacción antes de que se haya comprometido / completado o después de que se haya confirmado o completado.
-
beforeCommit()
devolución de llamadabeforeCommit()
dice que aún puede producirse una reversión después de que sebeforeCommit()
el método; -
beforeComplete()
se llama incluso si la transacción está fallando -
afterCommit/Complete()
después de que la transacción se haya comprometido realmente a la base de datos y no hay forma de deshacer.
Ahora que lo veo, parece que lo que quiero es otro en un protocolo de confirmación de dos fases; pero me pregunto si hay una solución en primavera. La diferencia es que la llamada realizada en la devolución de llamada no se puede deshacer.
(*) de Spring 4.2 es muy simple con @TransactionalEventListener
y TransactionPhase
que abstrae muy bien TransactionSynchronization
Solo quiero volver primero a una transacción, ya que es una unidad de trabajo que o bien todos pasan o todos fallan. Con lo que dice acerca de su método acerca de que no se puede revertir, y debe ejecutarse entre el inicio y el final de la transacción, lamento decir que no tiene una transacción.
Podría hacer un montón de comprobaciones en su método para asegurarse de que el posible inconveniente de una reversión sea extremadamente pequeño, pero siempre existirá la posibilidad de que su método se ejecute y ocurra una reversión, pero esta posibilidad podría ser extremadamente insignificante y usted podría estar feliz con eso, no sé.
Editar: Creo que una analogía sería agradable.
Caso 1: Ejemplo clásico de una transacción es comprar una banana en la tienda, si no tienes dinero, o la tienda no tiene plátano, la tienda no obtiene dinero, no obtienes una banana, esto es lo que normalmente sucede. Pero si se establecen todas las condiciones, la transacción se confirmará correctamente.
Caso 2: ahora por lo que estás preguntando. Por argumentos, digamos que eres un ladrón, y solo quieres robar el plátano si te salgas con la tuya. No puede saberlo con certeza, porque al preguntar sobre el futuro, a menos que sea un adivino, cuando vaya a robar el plátano podría quedar atrapado.
Si vuelves al primer caso, podrías verificar que tienes dinero, que la tienda tiene una banana, darle a la tienda tu dinero, echar a todos los clientes, cerrar las puertas de la tienda para que la tienda esté en un estado inmutable. Ve a hacer tu método que no puedes revertir, vuelve a la tienda y toma el plátano. Nadie puede asegurarle que la banana todavía estará allí, pero es muy probable.
Su caso es que uno de sus recursos no es compatible con la confirmación de dos fases (no compatible con XA ). Su idea va en la dirección del patrón descrito en el párrafo XA y el último Gambito de recursos de http://www.javaworld.com/article/2077963/open-source-tools/distributed-transactions-in-spring--with- y-sin-xa.html
El uso de la última gambita de recursos se explica brevemente en la respuesta a Cómo configurar Spring Boot + Bitronix + origen de datos no XA + XA JMS Connection
Por cierto, su pregunta no menciona qué implementación de un administrador de transacciones utiliza (JBossTS, Bitronix JTA, Atomikos Transaction Essentials, ...).