Home > database >  Rollback records executed in two separate Transnational code block in Spring Boot JPA
Rollback records executed in two separate Transnational code block in Spring Boot JPA

Time:02-20

I am calling two Transactional methods from my controller

Controller Class

@Autowired
DataService ds;

@RequestMapping("addData")
public  void addCasesDirect() {
    ds.functionA();
    ds.functionB();
}

DataService.java

@Service
public class DataService {

 @Transactional
 public void functionA(){

  -------
  entitydao.save(entitiy);
 }
 @Transactional
 public void functionB(){

  -------
  -------
  //Read Data Saved on executing functionA()
  //using EntityManager and NativeQuery
  -------
 }
}

The functionB() requires certain data that was inserted in the DB while execution of functionA(). Hence, I have used two seperate function instead of one single.

I want to achieve the two below things.

  1. I need to get the data inserted using functionA() when executing functionB()
  2. If functionB() fails, I want to rollback the changes of both functionA() and functionB()

I am able achieve the first point by using two separate blocks.But how can I achieve the second point.

Using: Java 8, Spring Boot 2.1.7, PostgreSQL

CodePudding user response:

This is wrong. I suggest you to read database transactions. Instead of doing this:

@Transactional
 public void functionA(){

  -------
  entitydao.save(entitiy);
 }
 @Transactional
 public void functionB(){

  -------
  -------
  //Read Data Saved on executing functionA()
  //using EntityManager and NativeQuery
  -------
 }

You should do this:

@Transactional
 public void functionA(){

  -------
  entitydao.save(entitiy);
  functionB();
 }

 public void functionB(){

  -------
  -------
  //Read Data Saved on executing functionA()
  //using EntityManager and NativeQuery
  -------
 }

Notice the call of functionB(). You need to call functionB() from functionA(). And not from the controller. Then then whole block [ functionA() and functionB() will act as a transactional block.]. So, when any of those fails the insertion done by functionA() and functionb() will roll back.

Your problem is you are treating functionA() and functionB() as two separate transactional block. So, your goal is not achieved. Rather you should consider themselves as a single block.

Pardon my english :)

CodePudding user response:

For (2) , you have to make sure that functionB and functionA execute in the same transaction.

For (1), you can simply return the data inserted from functionA such that you can pass it when calling functionB.

Something like below :

@Service
public class DataService {


     public Entity functionA(){
       return entitydao.save(entitiy);
     }
    
     public void functionB(Entity entity){

     }

     @Transactional
     public void foo(){
        Entity entity = functionA();
        functionB(entity);
     }
}

Then you controller method just calls foo() which ensure both functionA and functionB are in the same transaction.

  • Related