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

后端 未结 4 515
-上瘾入骨i
-上瘾入骨i 2020-12-07 14:15

Case1

@Transactional
public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
                    


        
相关标签:
4条回答
  • 2020-12-07 14:48

    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.

    0 讨论(0)
  • 2020-12-07 14:52

    @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.

    0 讨论(0)
  • 2020-12-07 14:55

    Quoting from here

    The Spring team's recommendation is that you only annotate concrete classes with the @Transactional annotation, as opposed to annotating interfaces.

    Since this mechanism is based on proxies, 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!

    0 讨论(0)
  • 2020-12-07 14:57

    Suppose you have the following class:

    @Transactional(readOnly = true)
    public class DefaultFooService implements FooService {
    
      public Foo getFoo(String fooName) {
        // do something
      }
    
      // these settings have precedence for this method
      @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
      public void updateFoo(Foo foo) {
        // do something
      }
    }
    

    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.

    More info:

    • Transaction management in Spring
    0 讨论(0)
提交回复
热议问题