What happens when I call one transactional method from another transactional method, now my second transactional method completed, and it came back in 1st transactional method, and unfortunately it fail, so will it roll back everything, means will it roll back 2nd transactional method changes..?? Note: both method are in same class
@Transactional
public void method1(){
//do something
call method2();
//do something
...
...
failed here
}
@Transactional
public void method2(){
//do something
save()
}
So in above example will it rollback whatever I saved in 2nd transactional method?
1 Answer. Show activity on this post. If you call method2() from method1() within the same class, the @Transactional annotation of the second method will not have any effect because it is not called through proxy, but directly.
If you call a method with a @Transactional annotation from a method with @Transactional belonging to the same Spring Bean , then the called methods transactional behavior will not have any impact on the transaction.
The @Transactional annotation makes use of the attributes rollbackFor or rollbackForClassName to rollback the transactions, and the attributes noRollbackFor or noRollbackForClassName to avoid rollback on listed exceptions. The default rollback behavior in the declarative approach will rollback on runtime exceptions.
The @Transactional annotation on the class level will be applied to every method in the class. However, when a method is annotated with @Transactional (like, updateFoo(Foo foo) ) this will take precedence over the transactional settings defined at the class level.
It depends on the txType. By default it is REQUIRED. So the first method starts the transaction and the same transaction is used for the call to method2.
Also be careful that a method call inside the same object does not trigger the transaction processing. As typically the transaction handling is handled as proxy that only works when calling an injected other bean. In your example you would not notice a difference though.
A case where this would matter is if method1 is not @Transactional and method2 is. In this case there would be no transaction at all.
If both methods are in the same class, the @Transactional
annotation won't even be considered when calling from another method of the same class. It doesn't matter what you put there, or even if you leave it out. There still will be a transaction started by method1()
, but then you're stuck in that transaction.
If the second method were in a separate class, you could use Propagation.REQUIRES_NEW
to have it run in its own transaction, meaning that even if method1()
later on failed, any changes in method2()
would still have made.
The default transaction propagation of REQUIRED
starts a new transaction if none exist, or joins an existing transaction. Again, in the separate class situation it results in the rollback of any changes made in method2()
when method1()
fails.
Spring boot provides concept of propagation with @Transactions. Propagation level decides that inner transaction should be part of same outer transaction or it should be different isolated one. By default propagation level is REQUIRED which means inner transaction will be part of same outer transaction, so if inner transaction fails whole transaction will get rollback.
Now its important to know that Rollback works for only Runtime exceptions by default. For checked Exceptions you have to specify that explicitly @Transcations(rollbackFor = Exception.class)
So to answer for your question is YES! It does rollback changes made by inner transaction.
this is a typical question:
this
notation, because another ways will call method2 and avoid call proxy object method, which contain all transactional logic.
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. @PostConstruct
@Transactional
parameters. For example - Use PROPAGATION_REQUIRES_NEW
for create new transaction for nested methods with @Transactional
. See more info in official doc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With