quarkus-hibernate-reactive + Vert.x EventBus 导致 java.lang.IllegalStateException:Session/EntityManager 已关闭

use*_*339 5 postgresql vert.x quarkus hibernate-reactive

我正在尝试将quarkus-hibernate-reactive扩展与quarkus-vertx扩展一起使用,但在保留数据方面遇到问题。我的项目大致如下:

水果资源:

@Inject
EventBus eventBus;

@POST
public Uni<Response> create(Fruit fruit) {
    if (fruit == null || fruit.getId() != null) {
        throw new WebApplicationException("Id was invalidly set on request.", 422);
    }

    return eventBus.<Void>request("create-fruit", fruit)
        .map(ignore -> Response.ok(fruit).status(201).build());
}
Run Code Online (Sandbox Code Playgroud)

水果服务:

@Inject
FruitRepository fruitRepository;

@ConsumeEvent("create-fruit")
public Uni<Void> createFruit(final Fruit fruit) {
    return fruitRepository.create(fruit);
}
Run Code Online (Sandbox Code Playgroud)

水果库:

@Inject
Mutiny.Session mutinySession;

public Uni<Void> create(final Fruit fruit) {
    return mutinySession
        .persist(fruit)
        .chain(mutinySession::flush);
}
Run Code Online (Sandbox Code Playgroud)

我得到的例外是 a java.lang.IllegalStateException: Session/EntityManager is closed,我认为发生在flush(). 我猜我的会话会在某个地方结束,但我不知道在哪里以及如何防止这种情况发生。

完整的示例可以在这里找到: https: //github.com/bamling/quarkus-hibernate-reactive-test FruitsEndpointTest模拟行为!

Rob*_*pek 0

好吧,我知道这个答案并不完全是您正在寻找的,但这是迄今为止我找到的唯一可行的解​​决方案。我将继续寻找一种方法来实现它并具有所有 Hibernate 优点,但这里是一个没有以下内容的解决方案:

@ApplicationScoped
public class FruitRepository {

    @Inject
    PgPool client;

    public Multi<Fruit> findAll() {
        return client.query("SELECT id, name FROM known_fruits ORDER BY name ASC").execute()
                .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
                .onItem().transform(FruitRepository::map);
    }

    public Uni<Void> create(final Fruit fruit) {
        return client.preparedQuery("INSERT INTO known_fruits (id, name) VALUES ($1, $2)")
                .execute(Tuple.tuple().addInteger(fruit.getId()).addString(fruit.getName()))
                .chain(e -> Uni.createFrom().voidItem());
    }

    public static Fruit map(Row row) {
        Fruit fruit = new Fruit();
        fruit.setId(row.getInteger("id"));
        fruit.setName(row.getString("name"));
        return fruit;
    }

}
Run Code Online (Sandbox Code Playgroud)

它有效,它是反应性的,但它也意味着手动管理对象关系。不理想。

更新:

这是一个使用 Hibernate 的工作示例。但是(!)它远非完美。虽然它更接近回答你的问题,但我总是更喜欢使用上面的例子而不是这个。会议应该关闭。我也想为 findAll 方法执行“withSession()”,但这会返回 Uni,而我们需要 Multi。尝试使用资源不起作用,因为这将在读取 Multi 之前关闭会话。因此,不要使用此代码,但也许它会帮助其他人提出更好的答案:

@ApplicationScoped
public class FruitRepository {

    private final Mutiny.SessionFactory sessionFactory;

    public FruitRepository(EntityManagerFactory entityManagerFactory) {
        this.sessionFactory = entityManagerFactory.unwrap(Mutiny.SessionFactory.class);
    }

    public Multi<Fruit> findAll() {
        Mutiny.Session session = sessionFactory.openSession();
        return session.createNamedQuery("Fruits.findAll", Fruit.class).getResults();
    }

    public Uni<Void> create(final Fruit fruit) {
        return sessionFactory.withSession(
                session -> session.persist(fruit)
                .chain(e -> Uni.createFrom().voidItem())
        );
    }
}
Run Code Online (Sandbox Code Playgroud)