09/08/2023

[Spring] Execute method in separate transaction

In Spring annotating a method as requiring a new transaction will not work if the caller of the method is in the same class.

We can easily work around this issue by creating a new class that will execute a given method in a new transaction:

 import org.springframework.stereotype.Service;  
 import org.springframework.transaction.annotation.Propagation;  
 import org.springframework.transaction.annotation.Transactional;  
   
 import java.util.function.Supplier;  
   
 /**  
  * Since spring ignores transaction settings for methods within the same class, we need a separate service  
  * to run isolated transactions which can be called from anywhere simply by supplying the method to execute  
  */  
 @Service  
 public class TransactionHandlerService {  
   
   /**  
    * Runs the given method in a the same transaction as the caller  
    *  
    * @param supplier the method to execute  
    * @param <T>  
    * @return the result of the invoked method  
    */  
   @Transactional(propagation = Propagation.REQUIRED)  
   public <T> T runInSameTransaction(Supplier<T> supplier) {  
     return supplier.get();  
   }  
   
   /**  
    * Runs the given method in a separate transaction  
    *  
    * @param supplier the method to execute  
    * @param <T>  
    * @return the result of the invoked method  
    */  
   @Transactional(propagation = Propagation.REQUIRES_NEW)  
   public <T> T runInNewTransaction(Supplier<T> supplier) {  
     return supplier.get();  
   }  
 }  

Then ensure the callers are annotated as @Transactional and simply pass the method to execute as input to our, for example:

transactionHandlerService.runInNewTransaction(() -> myMethod(someInput));

No comments:

Post a Comment

With great power comes great responsibility