HHH-10942 - Session not flushing starting from 5.2.0 in Karaf + Aries JPA & JTA

This commit is contained in:
Andrea Boriero 2016-07-11 14:10:50 +02:00
parent d55ade52b2
commit 109410b153
12 changed files with 101 additions and 122 deletions

View File

@ -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?
* <p/>
* 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.
*

View File

@ -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 extends SessionFactoryBuilder> T unwrap(Class<T> 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();

View File

@ -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;

View File

@ -50,6 +50,8 @@ public interface SessionFactoryOptionsState {
boolean isAllowOutOfTransactionUpdateOperations();
boolean isReleaseResourcesOnCloseEnabled();
Object getBeanManagerReference();
Object getValidatorFactoryReference();

View File

@ -368,6 +368,12 @@ public abstract class AbstractDelegatingSessionFactoryBuilder<T extends Abstract
return getThis();
}
@Override
public SessionFactoryBuilder enableReleaseResourcesOnCloseEnabled(boolean enable) {
delegate.enableReleaseResourcesOnCloseEnabled( enable );
return getThis();
}
@Override
@SuppressWarnings("unchecked")
public <S extends SessionFactoryBuilder> S unwrap(Class<S> type) {

View File

@ -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();

View File

@ -203,4 +203,6 @@ public interface SessionFactoryOptions {
boolean isProcedureParameterNullPassingEnabled();
boolean isAllowOutOfTransactionUpdateOperations();
boolean isReleaseResourcesOnCloseEnabled();
}

View File

@ -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();
}

View File

@ -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<String, Object> 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 {

View File

@ -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 );

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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?
* <p/>
* 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();
}