HHH-10877 - Fix Introduce a configuration option to allow out of transaction updates

This commit is contained in:
Andrea Boriero 2016-06-28 14:44:07 +02:00
parent 88e7254b6e
commit a8bcedecbf
10 changed files with 73 additions and 2 deletions

View File

@ -730,5 +730,15 @@ skipUnsupported:: Do the population, but ignore any non-JPA features that would
|`hibernate.delay_cdi_access`| `true` or `false` (default value) | Defines delayed access to CDI `BeanManager`. Starting in 5.1 the preferred means for CDI bootstrapping is through `org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager`. |`hibernate.delay_cdi_access`| `true` or `false` (default value) | Defines delayed access to CDI `BeanManager`. Starting in 5.1 the preferred means for CDI bootstrapping is through `org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager`.
|`hibernate.allow_update_outside_transaction` | `true` or `false` (default value) a|
Setting that allows to perform update operations outside of a transaction boundary.
Accepts two values:
true:: allows to flush an update out of a transaction
false:: does not allow
|===================================================================================================================================================================================================================================================== |=====================================================================================================================================================================================================================================================

View File

@ -687,6 +687,8 @@ public interface SessionFactoryBuilder {
*/ */
SessionFactoryBuilder applySqlFunction(String registrationName, SQLFunction sqlFunction); SessionFactoryBuilder applySqlFunction(String registrationName, SQLFunction sqlFunction);
SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow);
/** /**
* Allows unwrapping this builder as another, more specific type. * Allows unwrapping this builder as another, more specific type.
* *

View File

@ -106,6 +106,7 @@ import static org.hibernate.cfg.AvailableSettings.USE_SECOND_LEVEL_CACHE;
import static org.hibernate.cfg.AvailableSettings.USE_SQL_COMMENTS; import static org.hibernate.cfg.AvailableSettings.USE_SQL_COMMENTS;
import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE; import static org.hibernate.cfg.AvailableSettings.USE_STRUCTURED_CACHE;
import static org.hibernate.cfg.AvailableSettings.WRAP_RESULT_SETS; 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.engine.config.spi.StandardConverters.BOOLEAN;
/** /**
@ -464,6 +465,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return this; return this;
} }
@Override
public SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow) {
this.options.allowOutOfTransactionUpdateOperations = allow;
return this;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends SessionFactoryBuilder> T unwrap(Class<T> type) { public <T extends SessionFactoryBuilder> T unwrap(Class<T> type) {
@ -511,6 +518,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean flushBeforeCompletionEnabled; private boolean flushBeforeCompletionEnabled;
private boolean autoCloseSessionEnabled; private boolean autoCloseSessionEnabled;
private boolean jtaTransactionAccessEnabled; private boolean jtaTransactionAccessEnabled;
private boolean allowOutOfTransactionUpdateOperations;
// (JTA) transaction handling // (JTA) transaction handling
private boolean jtaTrackByThread; private boolean jtaTrackByThread;
@ -542,6 +550,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean orderUpdatesEnabled; private boolean orderUpdatesEnabled;
private boolean orderInsertsEnabled; private boolean orderInsertsEnabled;
// multi-tenancy // multi-tenancy
private MultiTenancyStrategy multiTenancyStrategy; private MultiTenancyStrategy multiTenancyStrategy;
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver; private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
@ -738,6 +747,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings ); this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings );
this.preferUserTransaction = ConfigurationHelper.getBoolean( PREFER_USER_TRANSACTION, configurationSettings, false ); this.preferUserTransaction = ConfigurationHelper.getBoolean( PREFER_USER_TRANSACTION, configurationSettings, false );
this.allowOutOfTransactionUpdateOperations = ConfigurationHelper.getBoolean(
ALLOW_UPDATE_OUTSIDE_TRANSACTION,
configurationSettings,
false
);
} }
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) { private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
@ -868,6 +882,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return jtaTransactionAccessEnabled; return jtaTransactionAccessEnabled;
} }
public boolean isAllowOutOfTransactionUpdateOperations() {
return allowOutOfTransactionUpdateOperations;
}
@Override @Override
public Object getBeanManagerReference() { public Object getBeanManagerReference() {
return beanManagerReference; return beanManagerReference;
@ -1159,6 +1177,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return options.isJtaTransactionAccessEnabled(); return options.isJtaTransactionAccessEnabled();
} }
public boolean isAllowOutOfTransactionUpdateOperations() {
return options.isAllowOutOfTransactionUpdateOperations();
}
@Override @Override
public Object getBeanManagerReference() { public Object getBeanManagerReference() {
return options.getBeanManagerReference(); return options.getBeanManagerReference();

View File

@ -53,6 +53,8 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
private final boolean autoCloseSessionEnabled; private final boolean autoCloseSessionEnabled;
private boolean jtaTransactionAccessEnabled; private boolean jtaTransactionAccessEnabled;
private boolean allowOutOfTransactionUpdateOperations;
// transaction handling // transaction handling
private final boolean jtaTrackByThread; private final boolean jtaTrackByThread;
private final boolean preferUserTransaction; private final boolean preferUserTransaction;
@ -126,6 +128,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
this.jpaBootstrap = state.isJpaBootstrap(); this.jpaBootstrap = state.isJpaBootstrap();
this.jtaTransactionAccessEnabled = state.isJtaTransactionAccessEnabled(); this.jtaTransactionAccessEnabled = state.isJtaTransactionAccessEnabled();
this.allowOutOfTransactionUpdateOperations = state.isAllowOutOfTransactionUpdateOperations();
this.sessionFactoryName = state.getSessionFactoryName(); this.sessionFactoryName = state.getSessionFactoryName();
this.sessionFactoryNameAlsoJndiName = state.isSessionFactoryNameAlsoJndiName(); this.sessionFactoryNameAlsoJndiName = state.isSessionFactoryNameAlsoJndiName();
@ -363,6 +366,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
return procedureParameterNullPassingEnabled; return procedureParameterNullPassingEnabled;
} }
@Override
public boolean isAllowOutOfTransactionUpdateOperations() {
return allowOutOfTransactionUpdateOperations;
}
@Override @Override
public boolean isSecondLevelCacheEnabled() { public boolean isSecondLevelCacheEnabled() {
return secondLevelCacheEnabled; return secondLevelCacheEnabled;

View File

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

View File

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

View File

@ -213,6 +213,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
return delegate.isProcedureParameterNullPassingEnabled(); return delegate.isProcedureParameterNullPassingEnabled();
} }
@Override
public boolean isAllowOutOfTransactionUpdateOperations() {
return delegate.isAllowOutOfTransactionUpdateOperations();
}
@Override @Override
public boolean isSecondLevelCacheEnabled() { public boolean isSecondLevelCacheEnabled() {
return delegate.isSecondLevelCacheEnabled(); return delegate.isSecondLevelCacheEnabled();

View File

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

View File

@ -1511,4 +1511,17 @@ public interface AvailableSettings {
*/ */
String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess"; String ALLOW_JTA_TRANSACTION_ACCESS = "hibernate.jta.allowTransactionAccess";
/**
* Setting that allows to perform update operations outside of a transaction boundary.
*
* Since version 5.2 Hibernate conforms with the JPA specification and does not allow anymore
* to flush any update out of a transaction boundary.
* <p/>
* Values are: {@code true} to allow flush operations out of a transaction, {@code false} to disallow.
* <p/>
* The default behavior is {@code false}
*
* @since 5.2
*/
String ALLOW_UPDATE_OUTSIDE_TRANSACTION = "hibernate.allow_update_outside_transaction";
} }

View File

@ -63,7 +63,6 @@ import org.hibernate.ObjectNotFoundException;
import org.hibernate.QueryException; import org.hibernate.QueryException;
import org.hibernate.ReplicationMode; import org.hibernate.ReplicationMode;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.SessionEventListener; import org.hibernate.SessionEventListener;
import org.hibernate.SessionException; import org.hibernate.SessionException;
@ -235,6 +234,7 @@ public final class SessionImpl
private transient boolean autoClose; private transient boolean autoClose;
private transient int dontFlushFromFind; private transient int dontFlushFromFind;
private transient boolean disallowOutOfTransactionUpdateOperations;
private transient ExceptionMapper exceptionMapper; private transient ExceptionMapper exceptionMapper;
private transient ManagedFlushChecker managedFlushChecker; private transient ManagedFlushChecker managedFlushChecker;
@ -253,6 +253,7 @@ public final class SessionImpl
this.autoClear = options.shouldAutoClear(); this.autoClear = options.shouldAutoClear();
this.autoClose = options.shouldAutoClose(); this.autoClose = options.shouldAutoClose();
this.disallowOutOfTransactionUpdateOperations = !factory.getSessionFactoryOptions().isAllowOutOfTransactionUpdateOperations();
if ( options instanceof SharedSessionCreationOptions && ( (SharedSessionCreationOptions) options ).isTransactionCoordinatorShared() ) { if ( options instanceof SharedSessionCreationOptions && ( (SharedSessionCreationOptions) options ).isTransactionCoordinatorShared() ) {
final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options; final SharedSessionCreationOptions sharedOptions = (SharedSessionCreationOptions) options;
@ -3388,7 +3389,7 @@ public final class SessionImpl
} }
private void checkTransactionNeeded() { private void checkTransactionNeeded() {
if ( !isTransactionInProgress() ) { if ( disallowOutOfTransactionUpdateOperations && !isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" ); throw new TransactionRequiredException( "no transaction is in progress" );
} }
} }