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.
- Service1 method having @Transactional would call a method of Service2. Service2 have @Transactional(isolation=Isolation.READ_UNCOMMITTED) which in turn will call the repository.
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>{
}
- Let Thread1 started TX1 and Thread2 started TX2.
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)?
- If Isolation cannot be changed once Transaction is initiated
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 solution I am trying now is to have to handle any exception in case of updation and then revert the DB lock operation manually. This is tedious in case we need to track many DB commits and revert the same. For the pseudocode refer Scenario2