Spring事务管理可以与Spring WebFlux一起使用吗?

时间:2018-12-26 16:08:18

标签: java spring spring-data-jpa spring-webflux

Spring对RDBMS事务管理的支持在Spring WebFlux中是否也起作用?

例如,假设配置正确,带有@Transactional注释的方法是否将使用Spring事务管理器并在发生错误时回滚该事务?

如果事务管理确实起作用,那么@Transactional方法实际上是否throw并异常,或者MonoFlux返回类型必须发出错误信号吗?

我知道JDBC本质上是阻塞的,因此任何JDBC操作都必须从阻塞过渡到反应性,反之亦然。

Spring事务管理器通过使用ThreadLocal(对吗?)工作,我假设它在Reactor环境中不起作用,因为Reactor在线程方面很节俭,并且一个线程可以换出一个当第一个正在等待I / O时,为另一个工作。我知道Reactor具有Context对象,该对象在概念上与ThreadLocal类似(对吗?),但是我还没有看到任何文档提到该事务使用了它。此外,事务中发生的所有JDBC操作必须使用相同的Connection,这在反应式上下文中可能很难做到。

我的组织具有WebFlux和Cassandra的经验,但是Cassandra具有本机响应式驱动程序。

谢谢!

2 个答案:

答案 0 :(得分:1)

AFAIK Spring标准交易管理不适用于WebFlux。

使用@Transactional将不起作用,因为在调用带注释的方法时,事务处理机制会将事务状态保存在调用线程的ThreadLocal中。如您自己所说,这是行不通的。它阻止并共享状态。

但是,您可以使用.runOn(Schedulers.parallel())来将阻止代码发送到另一个线程。这样,您就可以拥有一个带有可阻塞线程的线程池,可以将其配置为与数据库连接池相同的大小。

但是即使如此,由于胎面池重用线程的方式,您仍然不能依靠@Transactional。在标准Servlet体系结构中,每个HTTP请求只有一个线程。发送回响应后,线程将停止,这将关闭事务。但是在这种情况下,Reactor调度程序不会关闭线程,而是将其重用于其他事件。因此,即使您可以阻止,仍然会遇到与以前相同的问题。

您确实有您提到的Context选项,我认为这对Mono有用。我不确定它是否适用于Flux(我认为Flux中的所有事件都共享相同的上下文,这是您不想要的)。

另一种选择是将Touple2与T1用作业务对象,将T2用作事务上下文。不过我不建议这样做,因为您将业务逻辑与技术内容混在一起,并且使事情复杂化了。

我最好的选择是亲自进行事务/连接管理:

  1. 获得数据库连接
  2. 打开TX
  3. 执行阻止IO的操作
  4. 关闭TX
  5. 关闭/释放数据库连接

在阻塞线程上的所有代码块中。

这将更安全(无泄漏)并且更易于理解。另外,由于您基本上可以自己做所有事情,因此可以选择最适合您的情况的错误处理方式。

答案 1 :(得分:0)

@Transactional现在对Spring Reactive有效。

我不会在这里详细介绍。一切都在这篇文章中进行了解释:https://spring.io/blog/2019/05/16/reactive-transactions-with-spring