Hibernate-reactive: openSession() 返回错误“这需要在 Vert.x 事件循环上运行”

创建于 2021-05-12  ·  7评论  ·  资料来源: hibernate/hibernate-reactive

你好,

到目前为止,在使用 Hibernate 反应式 API (1.0.0.CR4) 时,Vertx 只是对我隐藏。 但是我必须公开一个 API 以返回一个会话,该会话将保持打开状态,直到使用此 API 的客户端决定关闭它。
我正在运行 Junit 测试,我有以下 API:

    public Stage.Session openSession() throws ExecutionException, InterruptedException {
        if (session != null && session.isOpen()) {
            session.close();
        }
        Stage.Session newSession = sessionFactory.openSession();
        this.session = newSession;
        return newSession ;
   }

在我的 junit 测试中:
Stage.Session session = deviceRepository.openSession();
当我运行代码时,出现错误:
This needs to be run on the Vert.x event loop
我尝试以多种不同的方式重构代码,但没有成功使其运行。

你能给我你的建议如何正确地做到这一点吗?

谢谢。

最有用的评论

好,我会的

所有7条评论

你好,
会话的问题在于它不是线程安全的,在不同的线程中使用它可能会导致难以调试的问题。 此外,创建新会话时会绑定到 Vert.x 上下文,之后需要在同一上下文中使用。

当使用SessionFactory#withTransactionSessionFactory#withSession时,这通常由 Hibernate Reactive 处理。

您的测试不起作用,因为它们运行在 JUnit 线程中,而不是 Vert.x 线程中。
在 JUnit 4 中解决此问题的一种方法是通过库io.vertx:vertx-unit:4.0.3包含的规则:

<strong i="13">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();

这将确保您的测试在 Vert.x 上下文中运行

但这还不够,您还需要确保会话绑定到规则定义的同一个 Vert.x 上下文。

VertxInstance 服务:

通常,实现此目的的方法是创建自定义VertxInstance 服务

该服务告诉 Hibernate Reactive 如何在创建会话时获取正确的 Vert.x 实例以使用。
如果您以编程方式创建 SessionFactory,下面是一个关于如何执行此操作的示例:

Configuration configuration = new Configuration();
StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
                .addService( VertxInstance.class, (VertxInstance) () -> getMyVertxInstance())
                .applySettings( configuration.getProperties() );
StandardServiceRegistry registry = builder.build();
SessionFactory sessionFactory = configuration.buildSessionFactory( registry );

或者,您可以使用JDK

  1. 在下面添加一个名为org.hibernate.reactive.vertx.VertxInstance的文本文件
    /META-INF/services/
  2. 文本文件将包含实现VertxInstance接口的类的路径:
    org.myproject.MyVertxProvider

现在 Hibernate Reactive 将在需要 Vert.x 实例时调用MyVertxProvider实例,并且如果您的代码在相同的 Vert.x 上下文中运行,则一切正常。

修复 JUnit 4 的问题:

回到测试,修复它们的一种方法是:

<strong i="41">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();

...

Configuration configuration = new Configuration();
StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
                .addService( VertxInstance.class, (VertxInstance) () -> vertxContextRule.vertx() )
                .applySettings( configuration.getProperties() );
SessionFactory sessionFactory = configuration.buildSessionFactory(  builder.build() );

如果您没有使用该规则,您可以通过以下方式在特定的 Vert.x 上下文中运行代码:

Context currentContext = Vertx.currentContext();
currentContext.runOnContext( event -> {
   // Here you should be able to use the session
});

您应该将刚刚写的内容作为常见问题添加到网站或其他任何地方。

好,我会的

@DavideD非常感谢您的解释。 谢谢。

我创建了一个问题来跟踪文档/网站的这些更改: https :

我要关闭这个问题。 有什么不清楚的可以多问。

谢谢你。

@DavideD是否可以在 JUnit 5 中使用您之前提到的以下代码?

Context currentContext = Vertx.currentContext();
currentContext.runOnContext( event -> {
   // Here you should be able to use the session
});

是的,该代码是 Vert.x,而不是 JUnit。

这里不是JUnit 5 的

<strong i="8">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();
此页面是否有帮助?
0 / 5 - 0 等级