Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@Transactional in Lambda Expressions

I use @transactional for DB update operations in normal functions.But in lambda expression @transactional in not allowed. How to handle this ? below is my code.

//normal function
  @Transactional
   void saveTransaction(String uniqueId) {
       Transaction transaction = new Transaction();
       transaction.setUniqueId(uniqueId);
       transactionRepository.save(transaction);
   }

   **@Transactional**  //Error Message - @Transactional not applicable to this field
   Consumer<String> saveTransaction = (uniqueId) ->
   {
       Transaction transaction = new Transaction();
       transaction.setUniqueId(uniqueId);
       transactionRepository.save(transaction);
   };
like image 273
sanjay Avatar asked Aug 08 '26 16:08

sanjay


2 Answers

You may use the Programmatic transaction management aproach.

The Spring Framework provides two means of programmatic transaction management:

  • Using the TransactionTemplate.
  • Using a PlatformTransactionManager implementation directly.

The Spring team generally recommends the TransactionTemplate for programmatic transaction management. The second approach is similar to using the JTA UserTransaction API, although exception handling is less cumbersome.

Firstly inject the TransactionTemplate reference in your bean.

  // single TransactionTemplate shared amongst all methods in this instance
  private final TransactionTemplate transactionTemplate;

Option 1

Initialize your Consumer<String> attribute within an initializer method annotated with @PostConstruct


        @PostConstruct
        public void init() {
            saveTransaction = (uniqueId) -> transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                      Transaction transaction = new Transaction();
                      transaction.setUniqueId(uniqueId);
                      transactionRepository.save(transaction);
                }
            });
        }

Option 2

Initialize Consumer<String> attribute within constructor


private final TransactionTemplate transactionTemplate;
private final Consumer<String> saveTransaction;

YourService(TransactionTemplate transactionTemplate) {
    this.transactionTemplate = transactionTemplate;
    saveTransaction = (uniqueId) -> transactionTemplate.execute(new TransactionCallbackWithoutResult() {
             protected void doInTransactionWithoutResult(TransactionStatus status) {
                      Transaction transaction = new Transaction();
                      transaction.setUniqueId(uniqueId);
                      transactionRepository.save(transaction);
                }
            });
}

According to Spring Docs:

Programmatic transaction management is usually a good idea only if you have a small number of transactional operations. For example, if you have a web application that require transactions only for certain update operations, you may not want to set up transactional proxies using Spring or any other technology. In this case, using the TransactionTemplate may be a good approach. Being able to set the transaction name explicitly is also something that can only be done using the programmatic approach to transaction management.

like image 72
eHayik Avatar answered Aug 10 '26 06:08

eHayik


@Transactional can be used with public functions only not on the variables. Lambda is not the function declaration. It is like variable declaration.

like image 26
Ankur Gupta Avatar answered Aug 10 '26 05:08

Ankur Gupta



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!