diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java index a47169ef6777d..d458ce63a33aa 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/JPAConfig.java @@ -14,8 +14,11 @@ import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; +import org.hibernate.SessionFactory; import org.jboss.logging.Logger; +import io.quarkus.hibernate.orm.runtime.session.JTASessionOptions; + @Singleton public class JPAConfig { @@ -114,13 +117,28 @@ EntityManagerFactory get() { throw new IllegalStateException("Persistence unit is closed"); } if (value == null) { - value = Persistence.createEntityManagerFactory(name); + value = create(); } } } return value; } + private EntityManagerFactory create() { + EntityManagerFactory result = Persistence.createEntityManagerFactory(name); + try { + JTASessionOptions.init(result.unwrap(SessionFactory.class)); + } catch (RuntimeException e) { + try { + result.close(); + } catch (RuntimeException e2) { + e.addSuppressed(e2); + throw e; + } + } + return result; + } + public synchronized void close() { closed = true; EntityManagerFactory emf = this.value; diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java index ab7a594f89bd2..44ea98d385395 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/boot/FastBootMetadataBuilder.java @@ -255,9 +255,6 @@ private MergedSettings mergeSettings(PersistenceUnitDescriptor persistenceUnit) cfg.putIfAbsent(AvailableSettings.CONNECTION_HANDLING, PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION); - // Auto-close sessions before transaction completion, as they should be when using JTA. - cfg.putIfAbsent(AvailableSettings.AUTO_CLOSE_SESSION, "true"); - if (readBooleanConfigurationValue(cfg, WRAP_RESULT_SETS)) { LOG.warn("Wrapping result sets is not supported. Setting " + WRAP_RESULT_SETS + " to false."); } diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/JTASessionOptions.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/JTASessionOptions.java new file mode 100644 index 0000000000000..480b8cd2b3ea4 --- /dev/null +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/JTASessionOptions.java @@ -0,0 +1,23 @@ +package io.quarkus.hibernate.orm.runtime.session; + +import org.hibernate.FlushMode; +import org.hibernate.SessionBuilder; +import org.hibernate.SessionFactory; +import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode; + +public class JTASessionOptions { + private static final String KEY = JTASessionOptions.class.getName(); + + public static void init(SessionFactory sessionFactory) { + SessionBuilder options = sessionFactory.withOptions() + .autoClose(true) // .owner() is deprecated as well, so it looks like we need to rely on deprecated code... + .connectionHandlingMode( + PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_RELEASE_BEFORE_TRANSACTION_COMPLETION) + .flushMode(FlushMode.ALWAYS); + sessionFactory.getProperties().put(KEY, options); + } + + public static SessionBuilder get(SessionFactory sessionFactory) { + return (SessionBuilder) sessionFactory.getProperties().get(KEY); + } +} diff --git a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java index f4046bfaee123..efb3e38122d51 100644 --- a/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java +++ b/extensions/hibernate-orm/runtime/src/main/java/io/quarkus/hibernate/orm/runtime/session/TransactionScopedSession.java @@ -34,6 +34,7 @@ import org.hibernate.NaturalIdLoadAccess; import org.hibernate.ReplicationMode; import org.hibernate.Session; +import org.hibernate.SessionBuilder; import org.hibernate.SessionEventListener; import org.hibernate.SessionFactory; import org.hibernate.SharedSessionBuilder; @@ -59,6 +60,7 @@ public class TransactionScopedSession implements Session { private final TransactionManager transactionManager; private final TransactionSynchronizationRegistry transactionSynchronizationRegistry; private final SessionFactory sessionFactory; + private final SessionBuilder jtaSessionOptions; private final String unitName; private final String sessionKey; private final Instance requestScopedSessions; @@ -71,6 +73,7 @@ public TransactionScopedSession(TransactionManager transactionManager, this.transactionManager = transactionManager; this.transactionSynchronizationRegistry = transactionSynchronizationRegistry; this.sessionFactory = sessionFactory; + this.jtaSessionOptions = JTASessionOptions.get(sessionFactory); this.unitName = unitName; this.sessionKey = this.getClass().getSimpleName() + "-" + unitName; this.requestScopedSessions = requestScopedSessions; @@ -82,7 +85,7 @@ SessionResult acquireSession() { if (session != null) { return new SessionResult(session, false, true); } - Session newSession = sessionFactory.openSession(); + Session newSession = jtaSessionOptions.openSession(); // The session has automatically joined the JTA transaction when it was constructed. transactionSynchronizationRegistry.putResource(sessionKey, newSession); // No need to flush or close the session upon transaction completion: