javaspringspring-transactions

Public method with @Transactional calling private method


I have a few questions about @Transactional annotation. If I have an implementation similar as below:

@Transactional
public Interface ExampleRepo {
    SampleClass createRecord();
}


public class RepoImpl implements ExampleRepo {

   public SampleClass createRecord() {
       return saveRecord();
   }

   private saveRecord() {
       //Saving record to Database.
   }
}

Will the transaction rollback as Spring will ignore if the @Transactional was called on a private method? But what if a public method annotated with @Transactional calls a private method that actually does the database operation.

Will this transaction be marked as rollback?


Solution

  • As per Spring Documentation

    Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. 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. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies ( proxy-target-class="true") or the weaving-based aspect ( mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.

    So, I would recommend to use @Transaction at method createRecord() level or RepoImpl class level.

    All code within a transaction scope runs in that transaction. However, you can specify the behavior if a transactional method is run when a transaction context already exists.

    When a method without @Transactional is called within a transaction block, the parent transaction will continue to exist for the new method. It will use the same connection from the parent method (method with @Transactional) and any exception caused in the called method (method without @Transactional) will cause the transaction to rollback as configured in the transaction definition.

    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.