如何在协程中处理 Spring 事务?

Yar*_*ykh 5 spring transactions kotlin kotlinx.coroutines

众所周知,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) {...}
} 
Run Code Online (Sandbox Code Playgroud)

Tom*_*der 1

首先,请记住,用 注释 bean 方法@Transactional是不够的 - 确保启用了声明性事务处理,例如通过添加@EnableTransactionManagement@Configuration类或在 XML 配置中使用 <tx-annotation-driven />

\n\n

关于你的问题:当执行 Spring bean 方法时,只有一个事务上下文,@Transactional当从包含类之外的 Spring bean 调用它们时,会注释这些方法!@TransactionalSpring 中的声明式事务依赖于Spring为带注释的类创建的 AOP 代理类。在运行时,如果 Spring bean A 调用@TransactionalSpring bean B 上的方法,该调用将被 AOP 代理拦截,该代理透明地生成事务,调用 Spring bean B 的原始方法,然后提交或回滚该事务。

\n\n

请记住:只有通过代理传入的外部方法调用才会被拦截 \xe2\x80\x93 任何自调用调用,如您的示例中的 this.process() 调用@Transactional方法this.success(),否则this.failure()不会启动任何事务 \xe2\x80\x93即使该方法带有注释@Transactional

\n