diff --git a/docs/src/main/asciidoc/hibernate-reactive.adoc b/docs/src/main/asciidoc/hibernate-reactive.adoc index 8816dbcd6c04f..7e103377617b4 100644 --- a/docs/src/main/asciidoc/hibernate-reactive.adoc +++ b/docs/src/main/asciidoc/hibernate-reactive.adoc @@ -208,13 +208,7 @@ Mutiny.SessionFactory sessionFactory; This will inject the `Mutiny.SessionFactory` of the default persistence unit. -You can also inject an instance of `Uni` using the exact same mechanism: - -[source,java] ----- -@Inject -Uni session; ----- +NOTE: Prior to Quarkus 3.0 it was also possible to inject a `@RequestScoped` bean for `Mutiny.Session`. However, the lifecycle of a reactive session does not fit the lifecycle of the CDI request context. Therefore, this bean is removed in Quarkus 3.0. [[testing]] === Testing diff --git a/extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java b/extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java index b1336aa1da174..e3e2effa6887f 100644 --- a/extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java +++ b/extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java @@ -64,7 +64,6 @@ import io.quarkus.hibernate.reactive.runtime.HibernateReactive; import io.quarkus.hibernate.reactive.runtime.HibernateReactiveRecorder; import io.quarkus.hibernate.reactive.runtime.ReactiveSessionFactoryProducer; -import io.quarkus.hibernate.reactive.runtime.ReactiveSessionProducer; import io.quarkus.reactive.datasource.deployment.VertxPoolBuildItem; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.configuration.ConfigurationException; @@ -87,13 +86,12 @@ void registerBeans(BuildProducer additionalBeans, Combi List descriptors, JpaModelBuildItem jpaModel) { if (descriptors.size() == 1) { - // Only register those beans if their EMF dependency is also available, so use the same guard as the ORM extension + // Only register the bean if their EMF dependency is also available, so use the same guard as the ORM extension additionalBeans.produce(new AdditionalBeanBuildItem(ReactiveSessionFactoryProducer.class)); - additionalBeans.produce(new AdditionalBeanBuildItem(ReactiveSessionProducer.class)); } else { LOG.warnf( - "Skipping registration of %s and %s because exactly one persistence unit is required for their registration", - ReactiveSessionFactoryProducer.class.getSimpleName(), ReactiveSessionProducer.class.getSimpleName()); + "Skipping registration of %s bean because exactly one persistence unit is required for their registration", + ReactiveSessionFactoryProducer.class.getSimpleName()); } } diff --git a/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/ConfigActiveFalseAndEntityTest.java b/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/ConfigActiveFalseAndEntityTest.java index 9fcf506db5f91..5a4073de0baa8 100644 --- a/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/ConfigActiveFalseAndEntityTest.java +++ b/extensions/hibernate-reactive/deployment/src/test/java/io/quarkus/hibernate/reactive/config/ConfigActiveFalseAndEntityTest.java @@ -3,9 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; - import jakarta.persistence.EntityManagerFactory; import org.hibernate.SessionFactory; @@ -15,8 +12,6 @@ import io.quarkus.arc.Arc; import io.quarkus.test.QuarkusUnitTest; -import io.vertx.core.Vertx; -import io.vertx.core.impl.ContextInternal; public class ConfigActiveFalseAndEntityTest { @@ -74,48 +69,4 @@ public void mutinySessionFactory() { "Hibernate Reactive was deactivated through configuration properties"); } - @Test - public void mutinySession() { - Mutiny.Session session = Arc.container().instance(Mutiny.Session.class).get(); - - // The bean is always available to be injected during static init - // since we don't know whether Hibernate Reactive will be active at runtime. - // So the bean cannot be null. - assertThat(session).isNotNull(); - // However, any attempt to use it at runtime will fail. - assertThatThrownBy(() -> runInVertxAndJoin(() -> { - try { - Arc.container().requestContext().activate(); - return session.find(MyEntity.class, 0L); - } finally { - Arc.container().requestContext().deactivate(); - } - })) - .cause() - .isInstanceOf(IllegalStateException.class) - .hasMessageContainingAll("Cannot retrieve the Mutiny.SessionFactory for persistence unit default-reactive", - "Hibernate Reactive was deactivated through configuration properties"); - } - - private T runInVertxAndJoin(Supplier action) { - CompletableFuture future = new CompletableFuture<>(); - runInVertx(() -> { - try { - future.complete(action.get()); - } catch (Throwable t) { - future.completeExceptionally(t); - } - }); - return future.join(); - } - - // Copied from org.hibernate.reactive.context.impl.VertxContext.execute. - // Unfortunately we can't use that class here, so we need to duplicate a few lines of code. - // This seems to be the simplest way to run code in Vertx from a test... - private void runInVertx(Runnable action) { - final io.vertx.core.Context newContext = Arc.container().instance(Vertx.class).get().getOrCreateContext(); - ContextInternal newContextInternal = (ContextInternal) newContext; - final ContextInternal duplicate = newContextInternal.duplicate(); - duplicate.runOnContext(ignored -> action.run()); - } } diff --git a/extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/ReactiveSessionProducer.java b/extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/ReactiveSessionProducer.java deleted file mode 100644 index 120c7baa6ee95..0000000000000 --- a/extensions/hibernate-reactive/runtime/src/main/java/io/quarkus/hibernate/reactive/runtime/ReactiveSessionProducer.java +++ /dev/null @@ -1,50 +0,0 @@ -package io.quarkus.hibernate.reactive.runtime; - -import java.util.concurrent.CompletableFuture; - -import jakarta.enterprise.context.RequestScoped; -import jakarta.enterprise.inject.Disposes; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -import org.hibernate.reactive.common.spi.MutinyImplementor; -import org.hibernate.reactive.mutiny.Mutiny; - -import io.quarkus.arc.DefaultBean; -import io.quarkus.arc.Unremovable; - -public class ReactiveSessionProducer { - - @Inject - MutinyImplementor mutinyImplementor; - - @Produces - @RequestScoped - @DefaultBean - @Unremovable - public Mutiny.Session createMutinySession() { - return mutinyImplementor.newSession(); - } - - public void disposeMutinySession(@Disposes Mutiny.Session reactiveSession) { - if (reactiveSession != null) { - //N.B. make sure to subscribe as this is a Mutiny based Session: - // operations don't happen at all if there is no subscription. - final CompletableFuture closeOperation = reactiveSession.close() - .subscribe() - .asCompletionStage(); - if (!io.vertx.core.Context.isOnVertxThread()) { - //When invoked from blocking code, behave as expected and block on the operation - //so to not starve resources with a deferred close. - closeOperation.join(); - } - // [else] no need to block. Worst that can happen is that the opening - // of a new Mutiny.Session needs to wait for an available connection, - // which implicitly orders it as "downstream" from the previous close - // to have actually happened as the connection pool is reactive. - // Also, if connections are available there is no real need to wait for - // it, so this should be good. - } - } - -} diff --git a/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2AlternativeTestEndpoint.java b/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2AlternativeTestEndpoint.java index aff8af60b2140..abc5414fd719a 100644 --- a/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2AlternativeTestEndpoint.java +++ b/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2AlternativeTestEndpoint.java @@ -16,7 +16,7 @@ public class HibernateReactiveDB2AlternativeTestEndpoint { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it us only used to // independently validate the contents of the database for the test @@ -28,14 +28,13 @@ public class HibernateReactiveDB2AlternativeTestEndpoint { public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + .chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { - return mutinySession.persist(new GuineaPig(10, "Tulip")) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip"))) .chain(() -> selectNameFromId(10)); } @@ -50,9 +49,8 @@ public Uni reactiveRemoveTransientEntity() { } return name; }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -62,9 +60,8 @@ public Uni reactiveRemoveTransientEntity() { @Path("/reactiveRemoveManagedEntity") public Uni reactiveRemoveManagedEntity() { return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -75,15 +72,13 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .onItem().transform(pig -> { - if (NEW_NAME.equals(pig.getName())) { - throw new AssertionError("Pig already had name " + NEW_NAME); - } - pig.setName(NEW_NAME); - return pig; - }) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5) + .invoke(pig -> { + if (NEW_NAME.equals(pig.getName())) { + throw new AssertionError("Pig already had name " + NEW_NAME); + } + pig.setName(NEW_NAME); + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2TestEndpoint.java b/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2TestEndpoint.java index 00cb438fd2ac9..6045686acf5cb 100644 --- a/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2TestEndpoint.java +++ b/integration-tests/hibernate-reactive-db2/src/main/java/io/quarkus/it/hibernate/reactive/db2/HibernateReactiveDB2TestEndpoint.java @@ -16,7 +16,7 @@ public class HibernateReactiveDB2TestEndpoint { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it us only used to // independently validate the contents of the database for the test @@ -28,14 +28,13 @@ public class HibernateReactiveDB2TestEndpoint { public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + .chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { - return mutinySession.persist(new GuineaPig(10, "Tulip")) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip"))) .chain(() -> selectNameFromId(10)); } @@ -50,9 +49,8 @@ public Uni reactiveRemoveTransientEntity() { } return name; }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -62,9 +60,8 @@ public Uni reactiveRemoveTransientEntity() { @Path("/reactiveRemoveManagedEntity") public Uni reactiveRemoveManagedEntity() { return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -75,15 +72,13 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .map(pig -> { - if (NEW_NAME.equals(pig.getName())) { - throw new AssertionError("Pig already had name " + NEW_NAME); - } - pig.setName(NEW_NAME); - return pig; - }) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5) + .invoke(pig -> { + if (NEW_NAME.equals(pig.getName())) { + throw new AssertionError("Pig already had name " + NEW_NAME); + } + pig.setName(NEW_NAME); + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLAlternativeTestEndpoint.java b/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLAlternativeTestEndpoint.java index ae2cc3f1aaba2..3809e0a13b1db 100644 --- a/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLAlternativeTestEndpoint.java +++ b/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLAlternativeTestEndpoint.java @@ -16,7 +16,7 @@ public class HibernateReactiveMySQLAlternativeTestEndpoint { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it us only used to // independently validate the contents of the database for the test @@ -28,14 +28,13 @@ public class HibernateReactiveMySQLAlternativeTestEndpoint { public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + .chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { - return mutinySession.persist(new GuineaPig(10, "Tulip")) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip"))) .chain(() -> selectNameFromId(10)); } @@ -50,9 +49,8 @@ public Uni reactiveRemoveTransientEntity() { } return name; }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction( + s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -62,9 +60,8 @@ public Uni reactiveRemoveTransientEntity() { @Path("/reactiveRemoveManagedEntity") public Uni reactiveRemoveManagedEntity() { return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -75,15 +72,13 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .map(pig -> { - if (NEW_NAME.equals(pig.getName())) { - throw new AssertionError("Pig already had name " + NEW_NAME); - } - pig.setName(NEW_NAME); - return pig; - }) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5) + .invoke(pig -> { + if (NEW_NAME.equals(pig.getName())) { + throw new AssertionError("Pig already had name " + NEW_NAME); + } + pig.setName(NEW_NAME); + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLTestEndpoint.java b/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLTestEndpoint.java index 360af9e0b2b52..eab04107aae9f 100644 --- a/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLTestEndpoint.java +++ b/integration-tests/hibernate-reactive-mysql/src/main/java/io/quarkus/it/hibernate/reactive/mysql/HibernateReactiveMySQLTestEndpoint.java @@ -16,7 +16,7 @@ public class HibernateReactiveMySQLTestEndpoint { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it us only used to // independently validate the contents of the database for the test @@ -28,14 +28,13 @@ public class HibernateReactiveMySQLTestEndpoint { public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + .chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { - return mutinySession.persist(new GuineaPig(10, "Tulip")) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip"))) .chain(() -> selectNameFromId(10)); } @@ -50,9 +49,8 @@ public Uni reactiveRemoveTransientEntity() { } return name; }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -62,9 +60,7 @@ public Uni reactiveRemoveTransientEntity() { @Path("/reactiveRemoveManagedEntity") public Uni reactiveRemoveManagedEntity() { return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -75,15 +71,13 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .map(pig -> { - if (NEW_NAME.equals(pig.getName())) { - throw new AssertionError("Pig already had name " + NEW_NAME); - } - pig.setName(NEW_NAME); - return pig; - }) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5) + .invoke(pig -> { + if (NEW_NAME.equals(pig.getName())) { + throw new AssertionError("Pig already had name " + NEW_NAME); + } + pig.setName(NEW_NAME); + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpoint.java b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpoint.java index 19aab4e624bd5..17f8f9e5457a4 100644 --- a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpoint.java +++ b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpoint.java @@ -18,7 +18,7 @@ public class HibernateReactiveTestEndpoint { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it's only used to // independently validate the contents of the database for the test @@ -29,16 +29,14 @@ public class HibernateReactiveTestEndpoint { @Path("/reactiveFindMutiny") public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); - return populateDB().chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + return populateDB().chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { final GuineaPig pig = new GuineaPig(10, "Tulip"); - return mutinySession - .persist(pig) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(pig)) .chain(() -> selectNameFromId(10)); } @@ -47,11 +45,10 @@ public Uni reactivePersist() { public Uni reactiveCowPersist() { final FriesianCow cow = new FriesianCow(); cow.name = "Carolina"; - return mutinySession - .persist(cow) - .chain(() -> mutinySession.flush()) - .chain(s -> mutinySession.createQuery("from FriesianCow f where f.name = :name", FriesianCow.class) - .setParameter("name", cow.name).getSingleResult()); + return sessionFactory.withTransaction(s -> s.persist(cow)) + .chain(() -> sessionFactory + .withSession(s -> s.createQuery("from FriesianCow f where f.name = :name", FriesianCow.class) + .setParameter("name", cow.name).getSingleResult())); } @GET @@ -63,9 +60,8 @@ public Uni reactiveRemoveTransientEntity() { if (name == null) throw new AssertionError("Database was not populated properly"); }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .map(result -> { if (result == null) @@ -84,9 +80,7 @@ public Uni reactiveRemoveManagedEntity() { if (name == null) throw new AssertionError("Database was not populated properly"); }) - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .map(result -> { if (result == null) @@ -101,13 +95,11 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .invoke(pig -> { + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5).invoke(pig -> { if (NEW_NAME.equals(pig.getName())) throw new AssertionError("Pig already had name " + NEW_NAME); pig.setName(NEW_NAME); - }) - .chain(() -> mutinySession.flush()) + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointAlternative.java b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointAlternative.java index 95dd3aa3ca721..2e2c63efba519 100644 --- a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointAlternative.java +++ b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointAlternative.java @@ -16,7 +16,7 @@ public class HibernateReactiveTestEndpointAlternative { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, it us only used to // independently validate the contents of the database for the test @@ -28,14 +28,13 @@ public class HibernateReactiveTestEndpointAlternative { public Uni reactiveFindMutiny() { final GuineaPig expectedPig = new GuineaPig(5, "Aloi"); return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, expectedPig.getId())); + .chain(() -> sessionFactory.withSession(s -> s.find(GuineaPig.class, expectedPig.getId()))); } @GET @Path("/reactivePersist") public Uni reactivePersist() { - return mutinySession.persist(new GuineaPig(10, "Tulip")) - .chain(() -> mutinySession.flush()) + return sessionFactory.withTransaction(s -> s.persist(new GuineaPig(10, "Tulip"))) .chain(() -> selectNameFromId(10)); } @@ -50,9 +49,8 @@ public Uni reactiveRemoveTransientEntity() { } return name; }) - .chain(() -> mutinySession.merge(new GuineaPig(5, "Aloi"))) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.merge(new GuineaPig(5, "Aloi")).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -62,9 +60,8 @@ public Uni reactiveRemoveTransientEntity() { @Path("/reactiveRemoveManagedEntity") public Uni reactiveRemoveManagedEntity() { return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .chain(aloi -> mutinySession.remove(aloi)) - .chain(() -> mutinySession.flush()) + .chain(() -> sessionFactory + .withTransaction(s -> s.find(GuineaPig.class, 5).chain(s::remove))) .chain(() -> selectNameFromId(5)) .onItem().ifNotNull().transform(result -> result) .onItem().ifNull().continueWith("OK"); @@ -75,15 +72,13 @@ public Uni reactiveRemoveManagedEntity() { public Uni reactiveUpdate() { final String NEW_NAME = "Tina"; return populateDB() - .chain(() -> mutinySession.find(GuineaPig.class, 5)) - .onItem().transform(pig -> { + .chain(() -> sessionFactory.withTransaction(s -> s.find(GuineaPig.class, 5).onItem().transform(pig -> { if (NEW_NAME.equals(pig.getName())) { throw new AssertionError("Pig already had name " + NEW_NAME); } pig.setName(NEW_NAME); return pig; - }) - .chain(() -> mutinySession.flush()) + }))) .chain(() -> selectNameFromId(5)); } diff --git a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointFetchLazy.java b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointFetchLazy.java index ef84e12ef8de7..f42d282da245c 100644 --- a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointFetchLazy.java +++ b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointFetchLazy.java @@ -20,7 +20,7 @@ public class HibernateReactiveTestEndpointFetchLazy { @Inject - Mutiny.Session mutinySession; + Mutiny.SessionFactory sessionFactory; // Injecting a Vert.x Pool is not required, It's used to // independently validate the contents of the database for the test @@ -30,16 +30,15 @@ public class HibernateReactiveTestEndpointFetchLazy { @GET @Path("/findBooksWithMutiny/{authorId}") public Uni> findBooksWithMutiny(@PathParam("authorId") Integer authorId) { - return mutinySession.find(Author.class, authorId) - .chain(author -> Mutiny.fetch(author.getBooks())); + return sessionFactory.withSession(s -> s.find(Author.class, authorId) + .chain(author -> Mutiny.fetch(author.getBooks()))); } @GET @Path("/getReferenceBooksWithMutiny/{authorId}") public Uni> getReferenceBooksWithMutiny(@PathParam("authorId") Integer authorId) { - return mutinySession - .fetch(mutinySession.getReference(Author.class, authorId)) - .chain(author -> Mutiny.fetch(author.getBooks())); + return sessionFactory.withSession(s -> s.fetch(s.getReference(Author.class, authorId)) + .chain(author -> Mutiny.fetch(author.getBooks()))); } @POST @@ -51,10 +50,10 @@ public Uni prepareDb() { author.getBooks().add(book1); author.getBooks().add(book2); - return mutinySession.createQuery(" delete from Book").executeUpdate() - .call(() -> mutinySession.createQuery("delete from Author").executeUpdate()) - .call(() -> mutinySession.persist(author)) - .chain(mutinySession::flush) + return sessionFactory.withTransaction(s -> s.createQuery(" delete from Book").executeUpdate() + .call(() -> s.createQuery("delete from Author").executeUpdate()) + .call(() -> s.persist(author)) + .chain(s::flush)) .chain(() -> selectNameFromId(author.getId())); } diff --git a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointJoinedSubclass.java b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointJoinedSubclass.java index fbbbc4d8d5e99..40c81fcdd03e4 100644 --- a/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointJoinedSubclass.java +++ b/integration-tests/hibernate-reactive-postgresql/src/main/java/io/quarkus/it/hibernate/reactive/postgresql/HibernateReactiveTestEndpointJoinedSubclass.java @@ -29,25 +29,23 @@ public class HibernateReactiveTestEndpointJoinedSubclass { @Inject - Mutiny.Session session; + Mutiny.SessionFactory sessionFactory; @DELETE @Path("/deleteBook/{bookId}") public Uni deleteBook(@PathParam("bookId") Integer bookId) { - return session.withTransaction(tx -> session + return sessionFactory.withTransaction(s -> s .createQuery("delete BookJS where id=:id") .setParameter("id", bookId) .executeUpdate()) - .chain(() -> session.find(SpellBook.class, bookId)); + .chain(() -> sessionFactory.withSession(s -> s.find(SpellBook.class, bookId))); } @POST @Path("/prepareDb") public Uni prepareDb() { final SpellBook spells = new SpellBook(6, "Necronomicon", true); - - return session.persist(spells) - .chain(session::flush); + return sessionFactory.withTransaction(s -> s.persist(spells)); } @Entity(name = "SpellBookJS")