@Transactional Method Called from Another Method Doesn't Obtain a Transaction

@Transactional method called from another method doesn't obtain a transaction

It is one of the limitations of Springs AOP. Because the dao bean is in fact a proxy when it is created by spring, it means that calling a method from within the same class will not call the advice (which is the transaction). The same goes for any other pointcut

Can @Transactional method call another @Transactional method without suspending?

As far as i know you can't do it with annotation REQUIRED_NEW.

But spring also support transaction manually with TransactionTemplate, TransactionDefinition.

we can use multiple definitions with just one PlatformTransactionManager.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/support/TransactionTemplate.html

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionDefinition.html

https://www.baeldung.com/spring-programmatic-transaction-management#4-custom-transaction-configurations

What happens if one @Transactional annotated method is calling another @Transactional annotated method on the same object instance?

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. Methods are enhanced with transactional behavior only if called through proxy (autowired bean, or some instance injected in any other way).

But generally speaking, if method1() and method2() were in different classes, and both were annotated with @Transactional (so using REQUIRED propagation), then they would share the same transaction started in method1().

Calling @Transactional method from non-transactional method in Spring 4.3

But this code works correctly in Spring 4.3.20. Is this rule actual
for Spring 4.3.20?

Yes. SonarLint is correct. Self-invocation cannot make @Transactional to take effect. It does not change even in Spring 5. That is how Spring AOP works (refer to docs). Your codes works most probably because you start another transaction inside itemDao (May be you have another @Transactional marked on ItemDao#addItems()).

if I make the second method as package-private, the SonarLint warning
disappears... Why?

Don't know why. Maybe it is a bug. As mentioned in this rule , it should give you warning when mark @Transactional in private method.

Call @Transactional annotated method from another @Transactional annotated method

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.

When calling a spring Non-Transactional method from a Transactional Method in another instance, does the transaction get propagated?

If there are no @Transactional annotations in B to tell it otherwise, then the b method uses the transaction established in the call to A.methoda. This is normal for Spring, we have components marked transactional that call DAOs that participate in the current transaction without being marked transactional themselves.

If you really want to suspend the current transaction, you can add this annotation to the b method:

@Transactional(propagation = Propagation.NOT_SUPPORTED)

There is a caveat about suspending transactions in the Spring API doc:

NOTE: Actual transaction suspension will not work out-of-the-box on all transaction managers. This in particular applies to JtaTransactionManager, which requires the javax.transaction.TransactionManager to be made available to it (which is server-specific in standard Java EE).

Spring Boot With @Transactional annotated method, calls other transactional methods and throws an Exception

Make sure that the method annotated with @Transactional is declared as public and called by a different class.

A transactional method must be public so that Spring can override it and it must be called from outside the defining class so that the invocation can go through a proxy.

It's one of the common pitfalls when using @Transactional, for more information see https://codete.com/blog/5-common-spring-transactional-pitfalls/



Related Topics



Leave a reply



Submit