Spring transaction behavior in private & internal methods
This post is to detail on the spring behavior when @Transactional annotations are applied on private methods or when transactional methods are called from within a method in the same class.
Transactional Private Methods
public class Bean { public void doStuff() { doPrivateStuff(); } @Transactional private void doPrivateStuff() { } } ... Bean bean = (Bean)appContext.getBean("bean"); bean.doStuff();
@Transactional
will have no effect if used to annotate private methods. The proxy generator will ignore them.
As per the Spring manual
Method visibility and @Transactional
When using proxies, you should apply the
@Transactional
annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional
annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ if you need to annotate non-public methods.
Calling internal transactional methods
public class Bean { public void doStuff() { doTransactionStuff(); } @Transactional public void doTransactionStuff() { } }
This will open a transaction:
Bean bean = (Bean)appContext.getBean("bean"); bean.doTransactionStuff();
This will not:
Bean bean = (Bean)appContext.getBean("bean"); bean.doStuff();
As per the Spring manual
Note: In proxy mode (which is the default), only ‘external’ method calls coming in through the proxy will be intercepted. This means that ‘self-invocation’, i.e. a method within the target object calling some other method of the target object, won’t lead to an actual transaction at runtime even if the invoked method is marked with @Transactional
!
Consider the use of AspectJ mode if you expect self-invocations to be wrapped with transactions as well. In this case, there won’t be a proxy in the first place; instead, the target class will be ‘weaved’ (i.e. its byte code will be modified) in order to turn @Transactional
into runtime behavior on any kind of method.
Summary
The @Transactional annotation defines a transaction boundary, and Spring will start/rollback/commit the transaction every time a @Transactional
-annotated method is entered or exited.
If you execute a @Transactional
-annotated method, and that method then calls another method in another class, and that one calls another one, which eventually does some database work, then you’re still inside the transaction.
Posted on May 20, 2011, in spring and tagged spring, transactions. Bookmark the permalink. 2 Comments.
Nice post
I am not sure where you are getting your info, but great topic.
I needs to spend some time learning more or understanding more.
Thanks for great info I was looking for this information for my mission.