“上下文中无交易”异常从何而来?

Mar*_*dik 6 mongodb spring-data-mongodb spring-boot project-reactor

我通过向spring-boot-starter-data-mongodb-reactiveSpring Boot 项目添加依赖项来使用反应式 MongoDb 驱动程序。升级到 Spring Boot 2.2.x 后出现此错误。

事实证明,如果我做一些简单的事情:

class Something(@Id val name: String)

@Repository
interface SomethingRepository: ReactiveCrudRepository<Something, String>

@SpringBootTest
class DemoApplicationTests
{
    @Autowired protected lateinit var repository: SomethingRepository

    @Test
    fun test()
    {
        repository
            .save( Something("1") )
            .onErrorContinue { throwable, _ -> println(throwable.message) }
            .block()
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到输出:

...
2019-12-12 20:58:48.379  INFO 24425 --- [    Test worker] com.example.demo.DemoApplicationTests    : Started DemoApplicationTests in 2.545 seconds (JVM running for 3.987)
No transaction in context
No transaction in context
...
Run Code Online (Sandbox Code Playgroud)

这看起来很奇怪,有几个原因:

  1. 对象成功保存到数据库中。
  2. 错误报告两次,即使管道由一个 Mono
  3. 的文档onErrorContinue显示,操作者下降引起的误差,这与1冲突的元素。
  4. 该错误是由 aNoTransactionInContextException的一部分引起的springframework.transaction,但我什至没有对交易做任何事情。

有没有人遇到过这个问题?这是框架中的错误,还是我做错了什么?

Ole*_*acs 5

onErrorContinue 将 OnNextFailureStrategy.ResumeStrategy 放入订阅者上下文中。此策略忽略元素。

当方法是事务性的时,Spring 将事务放入订阅者上下文中。然后 Spring 尝试在上下文中查找事务,如果事务不存在则抛出异常。默认情况下,Spring 在非事务性方法中忽略此异常并继续执行。但在onErrorContinue OnNextFailureStrategy.ResumeStrategy 的情况下,控制并忽略元素。

你可以试试这个:

Flux.just(something1, something2)
    .flatMap(this::save)
    .subscribe();
Run Code Online (Sandbox Code Playgroud)

...

private Mono<Something> save(Something s) {
        return Mono.just(s)
                   .flatMap(somethingRepository::save)
                   .onErrorResume(t -> {
                       log.error("Failed to save : {}", s, t);
                       return Mono.empty();
                   });
    }
Run Code Online (Sandbox Code Playgroud)