Reputation: 2165
Say I have the following spring beans in a spring boot app. My intent is to make createFoo()
transactional so:
barService.bar()
throws exceptions, the persist gets rolled back.barService.bar()
is NOT called.@Service
public class FooService
{
@Autowired
private FooRepository fooRepository;
@Autowired
private BarService barService;
@Transactional
public void createFoo(Foo foo) {
fooRepository.save(foo);
// expect to not execute when the above line throws exceptions
barService.bar();
}
}
@Service
public class BarService {
public void bar() {
}
}
So far the 1st requirement works, however the 2nd doesn't. When the persist throws exception, barService.bar()
is AlWAYS called.
If I remove @Transactional
, 2nd requirement works, the 1st doesn't.
I also tried all Propagation
types, none of them work as I expected. For example, if I use @Transactional(MANDATORY)
, I get the following error:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
Upvotes: 1
Views: 611
Reputation: 9266
Without @Transactional
, each call to a repo method is a standalone transaction and it will be flushed immediately. That's why your 2nd requirement worked without @Transactional
.
When you add @Transactional
, the whole createFoo()
becomes one single unit of transaction. Hence, the changes you make when calling save()
will only be flushed when createFoo()
completes its execution. That's why your 1st requirement worked with @Transactional
.
To achieve what you want, keep @Transactional
and call saveAndFlush()
instead of save()
.
Upvotes: 3