supongo que es necesario diferenciar entre transacción 'lógico' ámbitos y las transacciones físicas '' aquí ...
Lo PROPAGATION_REQUIRED crea un alcance de transacción lógica para cada método al que se aplica. Cada tal alcance de transacción lógica puede decidir individualmente sobre el estado de retrotraer solo, con una transacción externa siendo el alcance lógicamente independiente de el alcance interno de la transacción. Del curso , en el caso del comportamiento PROPAGATION_REQUIRED estándar , se asignarán a la misma transacción física a la misma transacción física . Por lo tanto, un marcador de solo retrotracción establecido en el alcance interno de la transacción afecta la probabilidad de la transacción externa de comprometerse realmente.Sin embargo, ya que el ámbito de transacción externa hizo no decidir sobre una reversión en sí, el rollback (silencio provocado por el alcance transacción interna) viene inesperado en ese nivel - que es por qué un UnexpectedRollbackException se tira.
PROPAGATION_REQUIRES_NEW, en contraste, utiliza una transacción completamente independiente para cada ámbito de transacción afectada . En ese caso, las transacciones físicas subyacentes serán diferentes y, por lo tanto, pueden confirmar o retrotraer de forma independiente, con una transacción externa que no se ve afectada por un estado de retrotracción de la transacción interna.
PROPAGATION_NESTED es diferente de nuevo en que utiliza una sola transacción física con múltiples puntos de retorno que puede volver a. Tales parciales rollbacks permiten un interior transacción alcance para desencadenar una reversión de su alcance , con la transacción exterior ser capaz de continuar la transacción física a pesar de algunas operaciones haber sido enrollado hacia atrás. Esto es típicamente mapeado en los puntos de guardado JDBC, , por lo que solo funcionará con las transacciones de recursos JDBC (Spring DataSourceTransactionManager).
Para completar la discusión: UnexpectedRollbackException puede también ser lanzada sin la aplicación cada vez haber establecido un marcador de reversión de sólo sí. En cambio, la infraestructura de la transacción puede haber decidido que el único resultado posible es una reversión , debido a restricciones en el estado de la transacción actual . Esto es particularmente relevante con XA transacciones.
Como he sugerido más arriba, lanzar una excepción en el interior de transacciones alcance, luego coger la excepción de que en el ámbito exterior y traducirlo en una llamada silenciosa setRollbackOnly no debe trabajar para su escenario. Un llamador de la transacción externa nunca verá una excepción. Dado que sólo preocuparse por esas reversiones silenciosas debido a los requisitos especiales impuestas por una persona que llama, yo incluso argumento que la solución arquitectónica correcta es utilizar excepciones dentro la capa de servicio, y para traducir esas excepciones en reversiones silenciosos en el nivel de fachada de servicio (derecha antes de volver a la llamada especial ).
Debido a que su problema no es posiblemente sólo alrededor de excepciones de rollback, pero más bien de cualquier excepción lanzada de su capa de servicios, que podría incluso utilizar estándar de excepción impulsada reversiones todo el camino a lo largo que capa de servicios, y luego coger y registrar tales excepciones vez que la transacción ya ha completado, de alguna fachada servicio adaptación que se traduce excepciones de su capa de servicio en la interfaz de usuario-error específico estados.
Juergen
Eso particular, única excepción es lanzada en ciertas circunstancias específicas, desde dentro de la infraestructura Spring TX. ¿Qué mensaje estaba dentro de 'UnexpectedRollbackException'? Eso nos ayudará a rastrearlo. – skaffman