众所周知,Spring事务与线程相关联:存在特定于正在进行的事务的线程本地。交易对协程背景一无所知。那么如果我想从协程中调用@Transactional方法怎么办呢:它安全吗?
想象一下,我们在JobProcessor bean中有一个处理作业列表的方法。每个作业都在async {}内处理。我希望在使用bean JobService的@Transactional方法成功或失败处理后更新数据库。
class JobProcessor {
fun process(jobs: List<MyJob>) =
jobs.map { job ->
async {
try {
....//processing
jobService.success(job)
} catch (t: Throwable) {
jobService.failure(job)
}
}
}
class JobService {
@Transactional
fun success(job: MyJob) {...}
@Transactional
fun failure(job: MyJob) {...}
}
首先,请记住使用@Transactional
注释bean方法是不够的 - 确保启用声明式事务处理,例如通过将@EnableTransactionManagement
添加到@Configuration
类或在XML配置中使用<tx-annotation-driven />
。
关于你的问题:当从包含类的Spring bean之外调用它们时,执行使用@Transactional
注释的Spring bean方法时,只会有一个事务上下文! Spring中的声明性事务依赖于Spring为@Transactional
注释类创建的AOP代理类。在运行时,如果Spring bean A在Spring bean B上调用@Transactional
方法,则调用将被AOP代理拦截,该代理透明地生成事务,调用Spring bean B的原始方法,然后提交或回滚此事务。
请记住:只有通过代理进入的外部方法调用才会被截获 - 任何自调用调用,如示例中调用@Transactional
方法的this.process()方法this.success()
或this.failure()
将不会启动任何事务 - 即使方法注释了@Transactional
。