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.
- I need to get the data inserted using
functionA()
when executingfunctionB()
- If
functionB()
fails, I want to rollback the changes of bothfunctionA()
andfunctionB()
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.