Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Transactional with static method

Why cant we use @Transactional for static methods to manage the transactions in my spring Project ?

@Transactional works well for non static method but not for static methods any specific reason ?

like image 710
Karibasappa G C Avatar asked May 09 '14 16:05

Karibasappa G C


People also ask

Can we use @transactional on private methods?

The answer your question is no - @Transactional will have no effect if used to annotate private methods. The proxy generator will ignore them. When using proxies, you should apply the @Transactional annotation only to methods with public visibility.

Can we use @transactional in service?

I USE THE @Transactional in @Controller and Just make a Generic Save Method and save all the entities/ model using this simple save method. and if any method fail to save then all the transactions in controller rollback successfully.

Can we use @transactional on interface?

You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies.

Can we use @transactional at class level?

Annotation Type Transactional. Describes a transaction attribute on an individual method or on a class. When this annotation is declared at the class level, it applies as a default to all methods of the declaring class and its subclasses.


2 Answers

In order to understand why something like what you are proposing does not work you have to first understand at a high level how Spring handles beans that use @Transactional.

When you annotate a method or the class as @Transactional and make it a Spring Bean, Spring effectively creates a proxy for that class (using JDK Dynamic proxies or CGLIB proxies). That means that whenever your class is used (from Spring managed code that is), it's not your code that gets called immediately, but the proxy which first does whatever is needed, and then your code is called (in the case of caching support your code would perhaps not even be called at all). A key thing to remember here is that the invoking code (the call site if you will) does not change at all, and the invocation of to the required target method (the proxy method) is performed by the JVM using the same bytecode (invokevirtual or invokeinterface).

With that in mind, the reason that static is not supported becomes clear. You can't create a proxy for static method! Of course Java Dynamic Proxies cannot do this, and neither can CGLIB.

Supporting such a feature would require changing the bytecode of the invoking code, since calling a static method is implemented via invokestatic in bytecode, which hard-codes the target method.

This part of the Spring documentation explains Spring AOP in details

like image 179
geoand Avatar answered Sep 28 '22 05:09

geoand


If you're using AspectJ, here's a simple, albeit ugly, workaround:

public static void doWhatever(final String param) {
    new Runnable() {
        @Transactional
        public void run() {
            // do whatever in transaction...
        }
    }.run();
}
like image 25
Archie Avatar answered Sep 28 '22 04:09

Archie