Cuando llama a un método que no está @Transactional
dentro de un bloque de transacción, la transacción principal continuará con el nuevo método. Utilizará la misma conexión del método principal (con @Transactional
) y cualquier excepción causada en el método llamado (sin, @Transactional
hará que la transacción se revierta como se configuró en la definición de transacción.
Si llama a un método con una @Transactional
anotación desde un método @Transactional
dentro de la misma instancia, entonces el comportamiento transaccional de los métodos llamados no tendrá ningún impacto en la transacción. Pero si llama a un método con una definición de transacción desde otro método con una definición de transacción, y están en diferentes instancias, entonces el código en el método llamado seguirá las definiciones de transacción dadas en el método llamado.
Puede encontrar más detalles en la sección Gestión declarativa de transacciones de la documentación de transacciones de primavera .
El modelo de transacción declarativa de Spring utiliza un proxy AOP. por lo que el proxy AOP es responsable de la creación de las transacciones. El proxy AOP estará activo solo si los métodos dentro de la instancia se llaman desde fuera de la instancia.
will follow the transaction definitions given in the called method
. Pero si la llamada proviene de la misma instancia de objeto, no tendrá ningún efecto, ya que la llamada no se propagará a través de los proxies aop que son responsables del mantenimiento de la transacción.@Transactional
definición de un objeto / instancia diferente, aunque el método de llamada tenga@Transactional
atributos diferentes , el método llamado seguirá su propia definición de transacción.Eso depende del nivel de propagación . Aquí están todos los posibles valores de nivel .
Por ejemplo, en caso de que un nivel de propagación esté ANIDADO, una transacción actual se "suspenderá" y se creará una nueva transacción ( nota: la creación real de una transacción anidada solo funcionará en administradores de transacciones específicos )
El nivel de propagación predeterminado (lo que usted llama "comportamiento") es REQUERIDO . En caso de que se llame a un método "interno" que tenga una
@Transactional
anotación (o se realice una transacción declarativa a través de XML), se ejecutará dentro de la misma transacción , por ejemplo, se crea "nada nuevo".fuente
@Transactional marca el límite de la transacción (inicio / finalización) pero la transacción en sí está vinculada al hilo. Una vez que se inicia una transacción, se propaga a través de las llamadas al método hasta que el método original regresa y la transacción se confirma / retrocede.
Si se llama a otro método que tiene una anotación @Transactional, entonces la propagación depende del atributo de propagación de esa anotación.
fuente
El método interno afectará al método externo si el método interno no está anotado con @Transactional.
En caso de que el método interno también esté anotado con @Transactional con
REQUIRES_NEW
, sucederá lo siguiente.... @Autowired private TestDAO testDAO; @Autowired private SomeBean someBean; @Override @Transactional(propagation=Propagation.REQUIRED) public void outerMethod(User user) { testDAO.insertUser(user); try{ someBean.innerMethod(); } catch(RuntimeException e){ // handle exception } } @Override @Transactional(propagation=Propagation.REQUIRES_NEW) public void innerMethod() { throw new RuntimeException("Rollback this transaction!"); }
El método interno está anotado
REQUIRES_NEW
y arroja una RuntimeException por lo que establecerá su transacción para deshacer pero NO EFECTUARÁ la transacción externa. La transacción externa se PAUSA cuando comienza la transacción interna y luego SE REANUDA DESPUÉS de que se concluye la transacción interna. Se ejecutan de forma independiente entre sí, por lo que la transacción externa PUEDE confirmarse correctamente.fuente