Reputation: 910
I have a service with a method, which is not annotated with @Transactional
:
@Service
@RequiredArgsConstructor
public class MainService {
private final ServiceA serviceA;
public void processData() {
List<EntityA> list = serviceA.getList();
list.forEach(item -> {
try {
serviceA.doSomeDbOperations(item);
} catch(Exception e) {
// some processing here
} finally {
// some processing and DB interactions here
}
})
}
}
The goal is to roll back the changes happened in try block (serviceA.doSomeDbOperations(item)
) if an exception is thrown. so I annotated this method in ServiceA with @Transactional
:
@Service
public class ServiceA {
// dependencies
@Transactional
public void doSomeDbOperations(EntityA item) {
// some logic here
repositoryA.save(item)
serviceB.deleteSomething(input)
}
}
serviceB.deleteSomething(input)
could throw an exception:
@Service
public class ServiceB {
// dependencies
public void deleteSomething(EntityA item) {
// some logic here
if(condition) {
Throw new RuntimeException();
}
}
}
The problem is that when an Exception is thrown, the changes in try block are not rolled back and data is non-consistent. Any idea where the problem is?
Upvotes: 3
Views: 2798
Reputation: 986
I guess in ServiceB you are using a checked Exception. In Spring the transactions are rolled back just on unchecked exceptions by default, so try throwing for example a RuntimeException in your ServiceB.deleteSomething() method.
In case you need a checked Exception there, you can do something like this in your ServiceA.doSomeDbOperations() method:
@Transactional(rollbackFor = Throwable.class)
Some references:
https://www.baeldung.com/java-checked-unchecked-exceptions
How to make Spring @Transactional roll back on all uncaught exceptions?
Upvotes: 1