如何在 Spring 引导服务中声明 `@Transactional` 从而引发异常 "immediately"?
How to declare `@Transactional` in a Spring Boot service so exception is thrown "immediately"?
假设我在 spring 引导应用程序中有以下 spring beans。我的目的是使 createFoo()
具有事务性,因此:
- 当
barService.bar()
抛出异常时,持久化被回滚。
- 当持久化抛出异常时,异常传播到调用者 "immediately" 所以
barService.bar()
不会被调用 .
@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() {
}
}
到目前为止,第一个要求有效,但第二个要求无效。当持久化抛出异常时,barService.bar()
总是被调用.
如果我删除 @Transactional
,第二个要求有效,第一个无效。
我还尝试了所有 Propagation
类型,其中 none 可以正常工作。例如,如果我使用 @Transactional(MANDATORY)
,我会得到以下错误:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
如果没有 @Transactional
,对 repo 方法的每次调用都是一个独立的事务,它将立即被刷新。这就是为什么您的第二个要求在没有 @Transactional
.
的情况下起作用的原因
当您添加 @Transactional
时,整个 createFoo()
成为一个交易单位。因此,您在调用 save()
时所做的更改只会在 createFoo()
完成执行时刷新。这就是为什么您的第一个要求适用于 @Transactional
.
要实现您想要的效果,请保留 @Transactional
并调用 saveAndFlush()
而不是 save()
。
假设我在 spring 引导应用程序中有以下 spring beans。我的目的是使 createFoo()
具有事务性,因此:
- 当
barService.bar()
抛出异常时,持久化被回滚。 - 当持久化抛出异常时,异常传播到调用者 "immediately" 所以
barService.bar()
不会被调用 .
@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() {
}
}
到目前为止,第一个要求有效,但第二个要求无效。当持久化抛出异常时,barService.bar()
总是被调用.
如果我删除 @Transactional
,第二个要求有效,第一个无效。
我还尝试了所有 Propagation
类型,其中 none 可以正常工作。例如,如果我使用 @Transactional(MANDATORY)
,我会得到以下错误:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
如果没有 @Transactional
,对 repo 方法的每次调用都是一个独立的事务,它将立即被刷新。这就是为什么您的第二个要求在没有 @Transactional
.
当您添加 @Transactional
时,整个 createFoo()
成为一个交易单位。因此,您在调用 save()
时所做的更改只会在 createFoo()
完成执行时刷新。这就是为什么您的第一个要求适用于 @Transactional
.
要实现您想要的效果,请保留 @Transactional
并调用 saveAndFlush()
而不是 save()
。