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.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 allowOutOfTransactionUpdateOperations(boolean allow);
/**
* 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_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;
/**
@ -464,6 +465,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return this;
}
@Override
public SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow) {
this.options.allowOutOfTransactionUpdateOperations = allow;
return this;
}
@Override
@SuppressWarnings("unchecked")
public <T extends SessionFactoryBuilder> T unwrap(Class<T> type) {
@ -511,6 +518,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean flushBeforeCompletionEnabled;
private boolean autoCloseSessionEnabled;
private boolean jtaTransactionAccessEnabled;
private boolean allowOutOfTransactionUpdateOperations;
// (JTA) transaction handling
private boolean jtaTrackByThread;
@ -542,6 +550,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean orderUpdatesEnabled;
private boolean orderInsertsEnabled;
// multi-tenancy
private MultiTenancyStrategy multiTenancyStrategy;
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
@ -738,6 +747,11 @@ 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
);
}
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
@ -868,6 +882,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return jtaTransactionAccessEnabled;
}
public boolean isAllowOutOfTransactionUpdateOperations() {
return allowOutOfTransactionUpdateOperations;
}
@Override
public Object getBeanManagerReference() {
return beanManagerReference;
@ -1159,6 +1177,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return options.isJtaTransactionAccessEnabled();
}
public boolean isAllowOutOfTransactionUpdateOperations() {
return options.isAllowOutOfTransactionUpdateOperations();
}
@Override
public Object getBeanManagerReference() {
return options.getBeanManagerReference();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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