Can the Isolation level be changed between the Same Transaction
I have a usecase where I want either the uncommited data that was persisted using saveAndFlush of SpringDataJpa to be available across different Transactions OR make the Inner Transaction commit the data but should be able to rollback in case of any exception in the outer transaction
This is needed as I want to update a resource and would have an entry in lock table to avoid concurrent updates. The lock table in DB is not getting updated untill the Update transaction is getting completed , hence I want to commit the data to lock table and at the same time should rollback in case of any exceptions during update operation.
Does the Service2 Isolation of READ_UNCOMMITED will take precedence or the Default one?
Does this Change in Isolation reflect in same Transaction that was propagated from Service1?
Scenario 1:
@Service
class Service1{
@Autowired
Service2 service2;
@Transactional
public void method1(){
Foo foo=new Foo();
foo.setId("f123");
service2.saveValue(foo);
}
}
@Service
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
class Service2{
@Autowired
FooRepository fooRepository;
public void saveValue(Foo value){
fooRepository.saveAndFlush(value);
}
}
public interface FooRepository extends JpaRepository<Foo, String>{
}
Scenario 2:
@Service
class Service1{
@Autowired
Service2 service2;
@Transactional
public void method1(){
Foo foo=new Foo();
foo.setId("f123");
service2.saveValue(foo);
try{
updateOperation()
}catch(Throwable e){ // does Spring @Transactional revert on ERRORS, by default it rollback on RuntimeException and Exception(in case we explicitly mention)?
service2.deleteByFooId(foo.getId());
throw e;
}
}
private void updateOperation(){
/* update logic for resource */- Not a DB update
}
@Service
@Transactional(propagation=Propagation.REQUIRES_NEW)
class Service2{
@Autowired
FooRepository fooRepository;
public void saveValue(Foo value){
fooRepository.saveAndFlush(value);
}
public void delete(String id){
deleteByFooId(id);
}
}
public interface FooRepository extends JpaRepository<Foo, String>{
}
Can TX2 access the uncommited data in case TX1 has executed the saveAndFlush but not yet commited to DB(as TX1 is not yet completed)?
Is there a way using Propagation or Isolation (or any other means) using which the inner transaction can be commited individually but can also rollback in case of any exception in the outer Transaction?
PROPAGATION_REQUIRES_NEW on Service2 method - will commit the data but in case of any exception in Service1 it wont rollback
PROPAGATION_NESTED on Service2 method - will commit data only when Service1 tx will commit
Is there any way to achieve the usecase highlighted in BOLD at the top?
The scenario 2 where in ..Propagation Require_New ..Is what I have used. And in case of any runtime exception during the parent method, I have handled that exception in try catch and reverted the lock which is updated in the DB as part of the new transaction and threw the same exception in catch block so that parent transaction gets reverted too.
This approach will be difficult in case you have many dB states to be reverted by you individually, but for now it suffice