Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between defining @Transactional on class vs method

Case1

@Transactional public class UserServiceImpl implements UserService {      ...................     public void method1(){         try{             method2();         }catch(Exception e){          }     }     public void method2(){      } } 

Case2

public class UserServiceImpl implements UserService {      ...................     public void method1(){         try{             method2();         }catch(Exception e){          }     }     @Transactional     public void method2(){      } } 

In case1 if any exception occurs it rollback is working, but in case 2 it's not working. Is there any performance issues if I follow the case1?

like image 746
Anil Kumar Avatar asked Apr 17 '14 12:04

Anil Kumar


People also ask

Can we use @transactional on class?

The @Transactional Annotation With transactions configured, we can now annotate a bean with @Transactional either at the class or method level: @Service @Transactional public class FooService { //... }

What is the function of the @transactional annotation at the 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.

Why applying Spring @transactional annotation on the concrete class or its methods is recommended rather than on interface?

Spring's recommendation is that you annotate the concrete implementations instead of an interface. It's not incorrect to use the annotation on an interface, it's just possible to misuse that feature and inadvertently bypass your @Transaction declaration.

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.


Video Answer


2 Answers

In case 1 @Transactional is applied to every public individual method. Private and Protected methods are Ignored by Spring.

Spring applies the class-level annotation to all public methods of this class that we did not annotate with @Transactional. However, if we put the annotation on a private or protected method, Spring will ignore it without an error.

In case 2 @Transactional is only applied to method2(), not on method1()

Case 1: - Invoking method1() -> a transaction is started. When method1() calls method2() no new transaction is started, because there is already one

Case 2: - Invoking method1() -> no transaction is started. When method1() calls method2() NO new transaction is started. This is because @Transactional does not work when calling a method from within the same class. It would work if you would call method2() from another class.

From the spring reference manual:

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.

like image 64
niekname Avatar answered Sep 19 '22 20:09

niekname


@Transactionalon a class applies to each method on the service. It is a shortcut. Typically, you can set @Transactional(readOnly = true) on a service class, if you know that all methods will access the repository layer. You can then override the behavior with @Transactional on methods performing changes in your model. Performance issues between 1) and 2) are not known.

like image 36
jeromerg Avatar answered Sep 19 '22 20:09

jeromerg