在 Spring Boot Transaction 中以只读方式执行 RxJava observable?

Posted

技术标签:

【中文标题】在 Spring Boot Transaction 中以只读方式执行 RxJava observable?【英文标题】:Execute RxJava observable as readOnly within Spring boot Transaction? 【发布时间】:2017-03-27 23:10:51 【问题描述】:

在我的 Spring Boot 应用程序中,我像这样异步调用了几个数据库:

public List<Results> doWork() 
        List<Observable<Results>> observables = Lists.newArrayList();

        observables.add(
          Observable.fromCallable(() -> dbQueryMethod(param1)).subscribeOn(Schedulers.io()));

        observables.add(
          Observable.fromCallable(() -> dbQueryMethod(param2)).subscribeOn(Schedulers.io()));

        return Observable.merge(observables)
                    .toList()
                    .toBlocking()
                    .single();


@Transactional(readOnly=true)
public List<Results> myServiceMethod() 
    doWork();

基本上问题是,尽管将我的服务层方法标记为事务和只读设置为 true,它实际上并没有将 ThreadLocal 状态传递给由 RxJava 生成的新线程,导致连接转到我的主数据库实例而不是只读副本。

我们目前正在使用已配置的ContextHandlersApp.java 中的ContextAwareSchedulerHook,但是我需要做什么才能使 RxJava 创建的新线程将继承所需的任何 ThreadLocal 状态,以便在定义的事务中管理它们?

【问题讨论】:

您可以使用 SchedulerHook 将本地线程复制到另一个线程,请参阅blog.mabn.pl/2014/11/rxjava-logback-and-mdc-threadlocal.html(适用于 RxJava 1) @dwursteisen 但是有什么可以说明如何专门针对春季 JDBC 状态执行此操作的吗? 【参考方案1】:

@Transactional(readOnly=true) 标记您的dbQueryMethod,并确保您通过Spring 自动装配代理(而不是直接来自同一个类)调用它。然后io线程将启动新事务,该事务是只读的。

【讨论】:

以上是关于在 Spring Boot Transaction 中以只读方式执行 RxJava observable?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2 / Kotlin / JDK9 - 引起:java.lang.ClassNotFoundException:javax.transaction.SystemExceptio

Spring Transaction:如果我不在方法上给出@Transaction 注释会发生啥

spring boot -- 事务

spring boot - 管理事务和多个数据源

用于过滤两个子实体的 Spring Boot 规范

spring boot 1.5.1.RELEASE 问题与休眠会话工厂创建有关