diff --git a/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java
index 048b83cdbb..4a112466f9 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java
@@ -689,6 +689,14 @@ public interface SessionFactoryBuilder {
SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow);
+ /**
+ * Should resources held by {@link javax.persistence.EntityManager} instance be released immediately on close?
+ *
+ * The other option is to release them as part of an afterQuery-transaction callback.
+ *
+ */
+ SessionFactoryBuilder enableReleaseResourcesOnCloseEnabled(boolean enable);
+
/**
* Allows unwrapping this builder as another, more specific type.
*
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
index f6b3307df0..a5e56f1fd5 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryBuilderImpl.java
@@ -108,6 +108,7 @@ import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS;
import static org.hibernate.cfg.AvailableSettings.ALLOW_UPDATE_OUTSIDE_TRANSACTION;
import static org.hibernate.engine.config.spi.StandardConverters.BOOLEAN;
+import static org.hibernate.jpa.AvailableSettings.DISCARD_PC_ON_CLOSE;
/**
* @author Gail Badner
@@ -471,6 +472,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return this;
}
+ @Override
+ public SessionFactoryBuilder enableReleaseResourcesOnCloseEnabled(boolean enable) {
+ this.options.releaseResourcesOnCloseEnabled = enable;
+ return this;
+ }
+
@Override
@SuppressWarnings("unchecked")
public T unwrap(Class type) {
@@ -519,6 +526,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean autoCloseSessionEnabled;
private boolean jtaTransactionAccessEnabled;
private boolean allowOutOfTransactionUpdateOperations;
+ private boolean releaseResourcesOnCloseEnabled;
// (JTA) transaction handling
private boolean jtaTrackByThread;
@@ -747,11 +755,18 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings );
this.preferUserTransaction = ConfigurationHelper.getBoolean( PREFER_USER_TRANSACTION, configurationSettings, false );
+
this.allowOutOfTransactionUpdateOperations = ConfigurationHelper.getBoolean(
ALLOW_UPDATE_OUTSIDE_TRANSACTION,
configurationSettings,
false
);
+
+ this.releaseResourcesOnCloseEnabled = ConfigurationHelper.getBoolean(
+ DISCARD_PC_ON_CLOSE,
+ configurationSettings,
+ false
+ );
}
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
@@ -886,6 +901,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return allowOutOfTransactionUpdateOperations;
}
+ @Override
+ public boolean isReleaseResourcesOnCloseEnabled() {
+ return releaseResourcesOnCloseEnabled;
+ }
+
@Override
public Object getBeanManagerReference() {
return beanManagerReference;
@@ -1181,6 +1201,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return options.isAllowOutOfTransactionUpdateOperations();
}
+ @Override
+ public boolean isReleaseResourcesOnCloseEnabled(){
+ return options.releaseResourcesOnCloseEnabled;
+ }
+
@Override
public Object getBeanManagerReference() {
return options.getBeanManagerReference();
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
index c081bd7a9d..2ca895a6b3 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsImpl.java
@@ -54,6 +54,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
private boolean jtaTransactionAccessEnabled;
private boolean allowOutOfTransactionUpdateOperations;
+ private boolean releaseResourcesOnCloseEnabled;
// transaction handling
private final boolean jtaTrackByThread;
@@ -371,6 +372,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
return allowOutOfTransactionUpdateOperations;
}
+ @Override
+ public boolean isReleaseResourcesOnCloseEnabled() {
+ return releaseResourcesOnCloseEnabled;
+ }
+
@Override
public boolean isSecondLevelCacheEnabled() {
return secondLevelCacheEnabled;
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
index 952fa2f3ff..876eb363a2 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsState.java
@@ -50,6 +50,8 @@ public interface SessionFactoryOptionsState {
boolean isAllowOutOfTransactionUpdateOperations();
+ boolean isReleaseResourcesOnCloseEnabled();
+
Object getBeanManagerReference();
Object getValidatorFactoryReference();
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java
index 594f8e0a07..fa125f9f52 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryBuilder.java
@@ -368,6 +368,12 @@ public abstract class AbstractDelegatingSessionFactoryBuilder S unwrap(Class type) {
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
index 8643d03914..2b327b9d20 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java
@@ -218,6 +218,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
return delegate.isAllowOutOfTransactionUpdateOperations();
}
+ @Override
+ public boolean isReleaseResourcesOnCloseEnabled() {
+ return delegate.isReleaseResourcesOnCloseEnabled();
+ }
+
@Override
public boolean isSecondLevelCacheEnabled() {
return delegate.isSecondLevelCacheEnabled();
diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
index 11e71dc2b0..129121e4e8 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java
@@ -203,4 +203,6 @@ public interface SessionFactoryOptions {
boolean isProcedureParameterNullPassingEnabled();
boolean isAllowOutOfTransactionUpdateOperations();
+
+ boolean isReleaseResourcesOnCloseEnabled();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java
index 793b0a922e..1a990f5664 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java
@@ -114,7 +114,8 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
private CacheMode cacheMode;
- private boolean closed;
+ protected boolean closed;
+ protected boolean waitingForAutoClose;
// transient & non-final for Serialization purposes - ugh
private transient SessionEventListenerManagerImpl sessionEventsManager = new SessionEventListenerManagerImpl();
@@ -306,6 +307,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
protected void setClosed() {
closed = true;
+ waitingForAutoClose = false;
cleanupOnClose();
}
@@ -342,6 +344,9 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
@Override
public boolean isTransactionInProgress() {
+ if ( waitingForAutoClose ) {
+ return transactionCoordinator.isTransactionActive();
+ }
return !isClosed() && transactionCoordinator.isTransactionActive();
}
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java
index 0991b6c641..1651292d6c 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java
@@ -242,6 +242,8 @@ public final class SessionImpl
private transient LoadEvent loadEvent; //cached LoadEvent instance
+ private transient boolean discardOnClose;
+
public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
super( factory, options );
@@ -254,6 +256,7 @@ public final class SessionImpl
this.autoClear = options.shouldAutoClear();
this.autoClose = options.shouldAutoClose();
this.disallowOutOfTransactionUpdateOperations = !factory.getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();
+ this.discardOnClose = getFactory().getSessionFactoryOptions().isReleaseResourcesOnCloseEnabled();
if ( options instanceof SharedSessionCreationOptions && ( (SharedSessionCreationOptions) options ).isTransactionCoordinatorShared() ) {
final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options;
@@ -302,6 +305,7 @@ public final class SessionImpl
private void applyEntityManagerSpecificProperties() {
for ( String key : ENTITY_MANAGER_SPECIFIC_PROPERTIES ) {
+ final Map properties = getFactory().getProperties();
if ( getFactory().getProperties().containsKey( key ) ) {
this.properties.put( key, getFactory().getProperties().get( key ) );
}
@@ -398,28 +402,26 @@ public final class SessionImpl
// todo : we want this check if usage is JPA, but not native Hibernate usage
if ( getSessionFactory().getSessionFactoryOptions().isJpaBootstrap() ) {
+ // Original hibernate-entitymanager EM#close behavior
+ checkSessionFactoryOpen();
checkOpen();
+ if ( discardOnClose || !isTransactionInProgress() ) {
+ super.close();
+ }
+ else {
+ //Otherwise, session auto-close will be enabled by shouldAutoCloseSession().
+ waitingForAutoClose = true;
+ closed = true;
+ }
}
+ else {
- super.close();
+ super.close();
- if ( getFactory().getStatistics().isStatisticsEnabled() ) {
- getFactory().getStatistics().closeSession();
+ if ( getFactory().getStatistics().isStatisticsEnabled() ) {
+ getFactory().getStatistics().closeSession();
+ }
}
-
-// Original hibernate-entitymanager EM#close behavior
-// does any of this need to be integrated?
-// checkSessionFactoryOpen();
-// checkOpen();
-//
-// if ( discardOnClose || !isTransactionInProgress() ) {
-// //close right now
-// if ( session != null ) {
-// session.close();
-// }
-// }
-// // Otherwise, session auto-close will be enabled by shouldAutoCloseSession().
-// open = false;
}
@Override
@@ -446,7 +448,7 @@ public final class SessionImpl
checkSessionFactoryOpen();
checkTransactionSynchStatus();
try {
- return !isClosed();
+ return !isClosed() && !waitingForAutoClose ;
}
catch (HibernateException he) {
throw exceptionConverter.convert( he );
@@ -465,17 +467,20 @@ public final class SessionImpl
}
private void managedFlush() {
- if ( isClosed() ) {
+ if ( isClosed() && !waitingForAutoClose ) {
log.trace( "Skipping auto-flush due to session closed" );
return;
}
log.trace( "Automatically flushing session" );
- flush();
+ doFlush();
}
@Override
public boolean shouldAutoClose() {
- if ( isClosed() ) {
+ if ( waitingForAutoClose ) {
+ return true;
+ }
+ else if ( isClosed() ) {
return false;
}
else if ( sessionOwner != null ) {
@@ -1383,10 +1388,13 @@ public final class SessionImpl
@Override
public void flush() throws HibernateException {
checkOpen();
+ doFlush();
+ }
+
+ private void doFlush() {
checkTransactionNeeded();
checkTransactionSynchStatus();
-
try {
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new HibernateException( "Flush during cascade is dangerous" );
@@ -2224,14 +2232,18 @@ public final class SessionImpl
@Override
public ActionQueue getActionQueue() {
- checkOpen();
+ if ( !waitingForAutoClose ) {
+ checkOpen();
+ }
// checkTransactionSynchStatus();
return actionQueue;
}
@Override
public PersistenceContext getPersistenceContext() {
- checkOpen();
+ if ( !waitingForAutoClose ) {
+ checkOpen();
+ }
// checkTransactionSynchStatus();
return persistenceContext;
}
@@ -3148,8 +3160,7 @@ public final class SessionImpl
@Override
public void flushBeforeTransactionCompletion() {
- final boolean doFlush = ! isClosed()
- && isTransactionFlushable()
+ final boolean doFlush = isTransactionFlushable()
&& getHibernateFlushMode() != FlushMode.MANUAL;
try {
diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
index ac7faff3ab..32a3aef5d0 100644
--- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/EntityManagerFactoryBuilderImpl.java
@@ -145,7 +145,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
private final StandardServiceRegistry standardServiceRegistry;
private final ManagedResources managedResources;
private final MetadataBuilderImplementor metamodelBuilder;
- private final SettingsImpl settings;
private static class JpaEntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable {
/**
@@ -200,7 +199,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// Build the "standard" service registry
ssrBuilder.applySettings( configurationValues );
- this.settings = configure( ssrBuilder );
+ configure( ssrBuilder );
this.standardServiceRegistry = ssrBuilder.build();
configure( standardServiceRegistry, mergedSettings );
@@ -580,11 +579,10 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
return new CacheRegionDefinition( cacheType, role, usage, region, lazyProperty );
}
- private SettingsImpl configure(StandardServiceRegistryBuilder ssrBuilder) {
- final SettingsImpl settings = new SettingsImpl();
+ private void configure(StandardServiceRegistryBuilder ssrBuilder) {
applyJdbcConnectionProperties( ssrBuilder );
- applyTransactionProperties( ssrBuilder, settings );
+ applyTransactionProperties( ssrBuilder );
// flush beforeQuery completion validation
if ( "true".equals( configurationValues.get( Environment.FLUSH_BEFORE_COMPLETION ) ) ) {
@@ -592,11 +590,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
LOG.definingFlushBeforeCompletionIgnoredInHem( Environment.FLUSH_BEFORE_COMPLETION );
}
- final Object value = configurationValues.get( DISCARD_PC_ON_CLOSE );
- if ( value != null ) {
- settings.setReleaseResourcesOnCloseEnabled( "true".equals( value ) );
- }
-
// final StrategySelector strategySelector = ssrBuilder.getBootstrapServiceRegistry().getService( StrategySelector.class );
// final Object interceptorSetting = configurationValues.remove( AvailableSettings.SESSION_INTERCEPTOR );
// if ( interceptorSetting != null ) {
@@ -604,8 +597,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// loadSessionInterceptorClass( interceptorSetting, strategySelector )
// );
// }
-
- return settings;
}
private void applyJdbcConnectionProperties(StandardServiceRegistryBuilder ssrBuilder) {
@@ -646,7 +637,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
}
}
- private void applyTransactionProperties(StandardServiceRegistryBuilder ssrBuilder, SettingsImpl settings) {
+ private void applyTransactionProperties(StandardServiceRegistryBuilder ssrBuilder) {
PersistenceUnitTransactionType txnType = PersistenceUnitTransactionTypeHelper.interpretTransactionType(
configurationValues.get( JPA_TRANSACTION_TYPE )
);
@@ -657,7 +648,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
// is it more appropriate to have this be based on bootstrap entry point (EE vs SE)?
txnType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
- settings.setTransactionType( txnType );
boolean hasTxStrategy = configurationValues.containsKey( TRANSACTION_COORDINATOR_STRATEGY );
if ( hasTxStrategy ) {
LOG.overridingTransactionStrategyDangerous( TRANSACTION_COORDINATOR_STRATEGY );
diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/SettingsImpl.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/SettingsImpl.java
deleted file mode 100644
index 797ae1e17c..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/internal/SettingsImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
- * See the lgpl.txt file in the root directory or .
- */
-package org.hibernate.jpa.boot.internal;
-
-import javax.persistence.spi.PersistenceUnitTransactionType;
-
-import org.hibernate.Interceptor;
-import org.hibernate.jpa.boot.spi.Settings;
-
-/**
- * @author Steve Ebersole
- */
-public class SettingsImpl implements Settings {
- private PersistenceUnitTransactionType transactionType;
- private boolean releaseResourcesOnCloseEnabled;
- private Class extends Interceptor> sessionInterceptorClass;
-
- @Override
- public PersistenceUnitTransactionType getTransactionType() {
- return transactionType;
- }
-
- public SettingsImpl setTransactionType(PersistenceUnitTransactionType transactionType) {
- this.transactionType = transactionType;
- return this;
- }
-
- @Override
- public boolean isReleaseResourcesOnCloseEnabled() {
- return releaseResourcesOnCloseEnabled;
- }
-
- public SettingsImpl setReleaseResourcesOnCloseEnabled(boolean releaseResourcesOnCloseEnabled) {
- this.releaseResourcesOnCloseEnabled = releaseResourcesOnCloseEnabled;
- return this;
- }
-
- @Override
- public Class extends Interceptor> getSessionInterceptorClass() {
- return sessionInterceptorClass;
- }
-
- public SettingsImpl setSessionInterceptorClass(Class extends Interceptor> sessionInterceptorClass) {
- this.sessionInterceptorClass = sessionInterceptorClass;
- return this;
- }
-}
diff --git a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Settings.java b/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Settings.java
deleted file mode 100644
index b775b32e89..0000000000
--- a/hibernate-core/src/main/java/org/hibernate/jpa/boot/spi/Settings.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Hibernate, Relational Persistence for Idiomatic Java
- *
- * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
- * See the lgpl.txt file in the root directory or .
- */
-package org.hibernate.jpa.boot.spi;
-
-import javax.persistence.spi.PersistenceUnitTransactionType;
-
-import org.hibernate.Interceptor;
-
-/**
- * @author Steve Ebersole
- */
-public interface Settings {
- public PersistenceUnitTransactionType getTransactionType();
-
- /**
- * Should resources held by {@link javax.persistence.EntityManager} instance be released immediately on close?
- *
- * The other option is to release them as part of an afterQuery-transaction callback.
- *
- * @return {@code true}/{@code false}
- */
- public boolean isReleaseResourcesOnCloseEnabled();
-
- public Class extends Interceptor> getSessionInterceptorClass();
-
-}