Spring Transaction Propagation
Spring has following transaction propagation behaviors:
-
REQUIRED - default behavior
The same transaction will be used if there is an already opened transaction in the current bean method execution context. If there is no existing transaction the Spring will create a new one.
This means that if an inner method causes a transaction to rollback, the outer method will fail to commit and will also rollback the transaction.
@Transactional(propagation=Propagation.REQUIRED) public void test1(Teacher t) { this.dao.testA(t); service2.updateStudent(); } @Transactional(propagation=Propagation.REQUIRES_REQUIRED) public void updateStudent() { throw new RuntimeException("Rollback!"); }
The only exceptions that set a transaction to rollback state by default are the unchecked exceptions (like RuntimeException). If you want checked exceptions to also set transactions to rollback you must configure them to do so, e.g. @Transactional(rollbackFor=Exception.class).
When using declarative transactions, ie by using only annotations, and calling methods from the same bean directly (self-invocation), the @Transactional annotation will be ignored by the container. If you want to enable transaction management in self-invocations you must configure the transactions using aspectj
-
REQUIRES_NEW
Spring will create a new physical transaction. That is outter transaction will not be affected by inner transaction result.
@Transactional(propagation=Propagation.REQUIRED) public void test1(Teacher t) { this.dao.testA(t); try { service2.updateStudent(); }catch(Exception e) { //handle exception } // int i = 1/0; } @Transactional(propagation=Propagation.REQUIRES_NEW) public void updateStudent() { throw new RuntimeException("Rollback!"); }
The outer transaction is paused when the inner transaction starts and then resumes after the inner transaction is finished.
If there is exception after executing
service2.updateStudent
, thenservice2.updateStudent
can commit success whilethis.dao.testA
will rolle back.Note : try-catch has to be added when calling inner transaction method, otherwise outter transaction still can be roll back
-
NESTED
Execute within a nested transaction if a current transaction exists, otherwise create a new one.
@Transactional(propagation=Propagation.REQUIRED) public void test1(Teacher t) { this.dao.testA(t); try { service2.updateStudent(); }catch(Exception e) { //handle exception } // int i = 1/0; } @Transactional(propagation=Propagation.NESTED) public void updateStudent() { throw new RuntimeException("Rollback!"); }
if there is exception in
service2.updateStudent()
, its behavior is the same asREQUIRES_NEW
.However if there is exception after
service2.updateStudent()
(e.g. addint i = 1/0
afterservice2.updateStudent()
) boththis.dao.testA
andservice2.updateStudent()
roll back.A savepoint will be taken at the start of the nested transaction. Íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.
-
MANDATORY
Support a current transaction, throw an exception if none exists.
-
NEVER
Execute non-transactionally, throw an exception if a transaction exists.
-
NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists.
-
SUPPORTS
Support a current transaction, execute non-transactionally if none exists.