Search code examples
javaoracle-databasespring-bootspring-data-jpaspring-transactions

How to partially rollback data in spring boot, errors to be persited


I have sequence of table data creation in transaction, using springboot, java, jpa and hibernate sequence shown below. Database used is Oracle

  1. Place order - insert into order details_table
  2. Process Payment - insert into payment_info table
  3. Error Message(info, warning, error) - insert into error_message table

I am inserting error messages in error_message table if any error occurs(info, warning, error).
My info and warning message get persisted into error_message if no error occurs during the processing of the request. But if there is an error, I am throwing an error from code to rollback the transaction, its working but my error_message also get rollback.

I want to rollback details_table and payment_info but not the error_message, I want them to be persisted.

How I can achieve the same?


Solution

  • Use two different transactions.

    The default transaction propagation is REQUIRED, when calling your @Transactional annotated method without a transactional context, a new transaction will be started but if there's already a transaction in place, the transaction will be joined, ending up with a single transaction. In case of rollback, all operations will be rollbacked as they belong to the same transaction.

    Change the transaction propagation to REQUIRES_NEW in order to always force starting a new transaction (instead of joining it if there's one). This will allow you to commit the error messages transaction independently from the payment info.

    @Transactional
    public void placeOrder(Order oder) {
      // process order
      
      paymentGateway.processPayment();
    
      // save order <- an exception here will rollback the current 
      // transaction but not the one in PaymentGateway which is independent
    } 
    
    // In PaymentGateway
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void processPayment() {
      // process payment
      // insert error messages
    }
    
    

    Further reading: Understanding PROPAGATION_REQUIRED. Make sure you also understand how exceptions affect transactions.