“上下文中无事务”异常来自何处?

时间:2019-12-12 20:39:29

标签: mongodb spring-boot spring-data-mongodb project-reactor

我正在通过向我的Spring Boot项目添加spring-boot-starter-data-mongodb-reactive依赖项来使用反应性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()
    }
}

我得到输出:

...
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
...

这似乎很奇怪,原因有两个:

  1. 对象已成功保存到数据库中。
  2. 即使管道由Mono
  3. 组成,也会报告两次错误 onErrorContinue中的
  4. The documentation建议操作员删除会导致错误的元素,该错误与1冲突。
  5. 该错误是由NoTransactionInContextException的一部分springframework.transaction引起的,但是我什至没有对事务进行任何操作。

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

1 个答案:

答案 0 :(得分:1)

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

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

您可以尝试以下方法:

Flux.just(something1, something2)
    .flatMap(this::save)
    .subscribe();

...

private Mono<Something> save(Something s) {
        return Mono.just(s)
                   .flatMap(gpsEventRepository::save)
                   .onErrorResume(t -> {
                       log.error("Failed to save : {}", s, t);
                       return Mono.empty();
                   });
    }