diff --git a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
index 4f16b157ff..55322866c0 100644
--- a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
+++ b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc
@@ -53,14 +53,34 @@ Note that for backwards compatibility, if a https://docs.jboss.org/hibernate/orm
|`hibernate.connection.password` or `javax.persistence.jdbc.password` | | Names the JDBC connection password.
|`hibernate.connection.isolation` | `REPEATABLE_READ` or
`Connection.TRANSACTION_REPEATABLE_READ` | Names the JDBC connection transaction isolation level.
-|`hibernate.connection.autocommit` | `true` or `false` (default value) | Names the JDBC connection autocommit mode.
-|`hibernate.connection.skip_autocommit_check` | `true` or `false` (default value) |
+|`hibernate.connection.autocommit` | `true` or `false` (default value) | Names the initial autocommit mode for JDBC Connections returned from a connection pool created in certain ConnectionProvider impl. See discussion of `hibernate.transaction.skip_setautocommit` as well.
-When using an external non-JTA `DataSource`, it might be that the underlying `DataSource` already disables the autocommit mode,
-so there is no need to check this `Connection` attribute upon starting a RESOURCE_LOCAL transaction.
+|`hibernate.connection.provider_disables_autocommit` | `true` or `false` (default value) |
-By setting it to `true`, the `Connection` acquisition can be delayed until the first SQL statement is needed to be executed.
-The connection acquisition delay allows you to reduce the database connection lease time, therefore allowing you to increase the transaction throughput.
+Indicates a promise by the user that Connections that Hibernate obtains from the configured ConnectionProvider
+have auto-commit disabled when they are obtained from that provider, whether that provider is backed by
+a DataSource or some other Connection pooling mechanism. Generally this occurs when:
+
+* Hibernate is configured to get Connections from an underlying DataSource, and that DataSource is already configured to disable auto-commit on its managed Connections
+* Hibernate is configured to get Connections from a non-DataSource connection pool and that connection pool is already configured to disable auto-commit. For the
+ Hibernate provided impls this will depend on the value of {@link #AUTOCOMMIT} setting.
+
+Hibernate uses this assurance as an opportunity to opt-out of certain operations that may have a performance
+ impact (although this impact is general negligible). Specifically, when a transaction is started via the
+ Hibernate or JPA transaction APIs Hibernate will generally immediately acquire a Connection from the
+ provider and:
+
+* check whether the Connection is initially in auto-commit mode via a call to `Connection#getAutocommit` to know how to clean up the Connection when released.
+* start a JDBC transaction by calling `Connection#setAutocommit(false)`
+
+We can skip both of those steps if we know that the ConnectionProvider will always return Connections with auto-commit disabled.
+ That is the purpose of this setting. By setting it to `true`, the `Connection` acquisition can be delayed until the first
+ SQL statement is needed to be executed. The connection acquisition delay allows you to reduce the database connection lease
+ time, therefore allowing you to increase the transaction throughput.
+
+Please note however that it is inappropriate to set this value to `true` when the Connections Hibernate gets
+ from the provider do not in fact have auto-commit disabled - doing so will lead to Hibernate executing SQL operations
+ outside of any JDBC/SQL transaction.
|`hibernate.connection.datasource` | |
@@ -529,6 +549,7 @@ The ability to handle this situation requires checking the Thread ID every time
|`hibernate.transaction.factory_class` | | This is a legacy setting that's been deprecated and you should use the `hibernate.transaction.jta.platform` instead.
+
|===================================================================================================================================================================================================================================
[[configurations-multi-tenancy]]
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 4a112466f9..ebf7f16b93 100644
--- a/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/boot/SessionFactoryBuilder.java
@@ -663,6 +663,11 @@ public interface SessionFactoryBuilder {
@Deprecated
SessionFactoryBuilder applyConnectionReleaseMode(ConnectionReleaseMode connectionReleaseMode);
+ /**
+ * @see org.hibernate.cfg.AvailableSettings#CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT
+ */
+ SessionFactoryBuilder applyConnectionProviderDisablesAutoCommit(boolean providerDisablesAutoCommit);
+
/**
* Should Hibernate apply comments to SQL it generates?
*
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 f9cb5f7e5d..a9ee66a01f 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
@@ -44,6 +44,7 @@ import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.config.internal.ConfigurationServiceImpl;
import org.hibernate.engine.config.spi.ConfigurationService;
+import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
@@ -406,6 +407,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return this;
}
+ @Override
+ public SessionFactoryBuilder applyConnectionProviderDisablesAutoCommit(boolean providerDisablesAutoCommit) {
+ this.options.connectionProviderDisablesAutoCommit = providerDisablesAutoCommit;
+ return this;
+ }
+
@Override
public SessionFactoryBuilder applySqlComments(boolean enabled) {
this.options.commentsEnabled = enabled;
@@ -553,6 +560,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
private boolean scrollableResultSetsEnabled;
private boolean commentsEnabled;
private PhysicalConnectionHandlingMode connectionHandlingMode;
+ private boolean connectionProviderDisablesAutoCommit;
private boolean wrapResultSetsEnabled;
private TimeZone jdbcTimeZone;
private boolean queryParametersValidationEnabled;
@@ -725,6 +733,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
this.jdbcFetchSize = ConfigurationHelper.getInteger( STATEMENT_FETCH_SIZE, configurationSettings );
this.connectionHandlingMode = interpretConnectionHandlingMode( configurationSettings, serviceRegistry );
+ this.connectionProviderDisablesAutoCommit = ConfigurationHelper.getBoolean(
+ AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT,
+ configurationSettings,
+ false
+ );
this.commentsEnabled = ConfigurationHelper.getBoolean( USE_SQL_COMMENTS, configurationSettings );
@@ -1155,6 +1168,10 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return connectionHandlingMode;
}
+ public boolean connectionProviderDisablesAutoCommit() {
+ return connectionProviderDisablesAutoCommit;
+ }
+
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return getPhysicalConnectionHandlingMode().getReleaseMode();
@@ -1478,6 +1495,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return options.getPhysicalConnectionHandlingMode();
}
+ @Override
+ public boolean connectionProviderDisablesAutoCommit() {
+ return options.connectionProviderDisablesAutoCommit();
+ }
+
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return getPhysicalConnectionHandlingMode().getReleaseMode();
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 bf93c5da54..55e0505f6b 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
@@ -121,6 +121,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
private final boolean scrollableResultSetsEnabled;
private final boolean commentsEnabled;
private final PhysicalConnectionHandlingMode physicalConnectionHandlingMode;
+ private final boolean connectionProviderDisablesAutoCommit;
private final boolean wrapResultSetsEnabled;
private final TimeZone jdbcTimeZone;
@@ -192,6 +193,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
this.schemaAutoTooling = state.getSchemaAutoTooling();
this.physicalConnectionHandlingMode = state.getPhysicalConnectionHandlingMode();
+ this.connectionProviderDisablesAutoCommit = state.connectionProviderDisablesAutoCommit();
this.getGeneratedKeysEnabled = state.isGetGeneratedKeysEnabled();
this.jdbcBatchSize = state.getJdbcBatchSize();
this.jdbcBatchVersionedData = state.isJdbcBatchVersionedData();
@@ -490,6 +492,11 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
return physicalConnectionHandlingMode.getReleaseMode();
}
+ @Override
+ public boolean doesConnectionProviderDisableAutoCommit() {
+ return connectionProviderDisablesAutoCommit;
+ }
+
@Override
public boolean isCommentsEnabled() {
return commentsEnabled;
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 25c12cccc4..a1158c811c 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
@@ -155,6 +155,8 @@ public interface SessionFactoryOptionsState {
PhysicalConnectionHandlingMode getPhysicalConnectionHandlingMode();
+ boolean connectionProviderDisablesAutoCommit();
+
/**
* @deprecated Use {@link #getPhysicalConnectionHandlingMode()} instead
*/
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 fa125f9f52..4b662a5877 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
@@ -348,6 +348,12 @@ public abstract class AbstractDelegatingSessionFactoryBuilder
+ * Default value is {@code false} - do not skip, aka call setAutocommit
*
* @since 5.2.10
*/
- String SKIP_AUTOCOMMIT_CHECK ="hibernate.connection.skip_autocommit_check";
+ String CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT= "hibernate.connection.provider_disables_autocommit";
/**
* Names a prefix used to define arbitrary JDBC connection properties. These properties are passed along to
diff --git a/hibernate-core/src/main/java/org/hibernate/internal/JdbcSessionContextImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/JdbcSessionContextImpl.java
index 0af612615f..da6c9f3ca7 100644
--- a/hibernate-core/src/main/java/org/hibernate/internal/JdbcSessionContextImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/internal/JdbcSessionContextImpl.java
@@ -60,6 +60,11 @@ public class JdbcSessionContextImpl implements JdbcSessionContext {
return connectionHandlingMode;
}
+ @Override
+ public boolean doesConnectionProviderDisableAutoCommit() {
+ return settings().doesConnectionProviderDisableAutoCommit();
+ }
+
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return connectionHandlingMode.getReleaseMode();
diff --git a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java
index 86b1b0bd70..0af3f3108f 100644
--- a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java
+++ b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/AbstractLogicalConnectionImplementor.java
@@ -62,7 +62,7 @@ public abstract class AbstractLogicalConnectionImplementor implements LogicalCon
@Override
public void begin() {
try {
- if ( !isSkipAutoCommitCheck() ) {
+ if ( !doConnectionsFromProviderHaveAutoCommitDisabled() ) {
log.trace( "Preparing to begin transaction via JDBC Connection.setAutoCommit(false)" );
getConnectionForTransactionManagement().setAutoCommit( false );
log.trace( "Transaction begun via JDBC Connection.setAutoCommit(false)" );
@@ -139,7 +139,7 @@ public abstract class AbstractLogicalConnectionImplementor implements LogicalCon
return status;
}
- protected boolean isSkipAutoCommitCheck() {
+ protected boolean doConnectionsFromProviderHaveAutoCommitDisabled() {
return false;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/LogicalConnectionManagedImpl.java b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/LogicalConnectionManagedImpl.java
index d6242c8e41..96517fc45a 100644
--- a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/LogicalConnectionManagedImpl.java
+++ b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/internal/LogicalConnectionManagedImpl.java
@@ -46,7 +46,7 @@ public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImple
private transient Connection physicalConnection;
private boolean closed;
- private boolean skipAutoCommitCheck;
+ private boolean providerDisablesAutoCommit;
public LogicalConnectionManagedImpl(
JdbcConnectionAccess jdbcConnectionAccess,
@@ -76,14 +76,16 @@ public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImple
acquireConnectionIfNeeded();
}
- ConfigurationService configurationService = jdbcSessionContext.getServiceRegistry()
- .getService( ConfigurationService.class );
-
- this.skipAutoCommitCheck = configurationService.getSetting(
- AvailableSettings.SKIP_AUTOCOMMIT_CHECK,
- StandardConverters.BOOLEAN,
- false
- );
+ this.providerDisablesAutoCommit = jdbcSessionContext.doesConnectionProviderDisableAutoCommit();
+ if ( providerDisablesAutoCommit ) {
+ log.debug(
+ "`hibernate.connection.provider_disables_autocommit` was enabled. This setting should only be " +
+ "enabled when you are certain that the Connections given to Hibernate by the " +
+ "ConnectionProvider have auto-commit disabled. Enabling this setting when the " +
+ "Connections do not have auto-commit disabled will lead to Hibernate executing " +
+ "SQL operations outside of any JDBC/SQL transaction."
+ );
+ }
}
private PhysicalConnectionHandlingMode determineConnectionHandlingMode(
@@ -265,7 +267,7 @@ public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImple
@Override
public void begin() {
- initiallyAutoCommit = !isSkipAutoCommitCheck() && determineInitialAutoCommitMode(
+ initiallyAutoCommit = !doConnectionsFromProviderHaveAutoCommitDisabled() && determineInitialAutoCommitMode(
getConnectionForTransactionManagement() );
super.begin();
}
@@ -279,7 +281,7 @@ public class LogicalConnectionManagedImpl extends AbstractLogicalConnectionImple
}
@Override
- protected boolean isSkipAutoCommitCheck() {
- return skipAutoCommitCheck;
+ protected boolean doConnectionsFromProviderHaveAutoCommitDisabled() {
+ return providerDisablesAutoCommit;
}
}
diff --git a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/spi/JdbcSessionContext.java b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/spi/JdbcSessionContext.java
index 4abb6726a9..8116dd04ec 100644
--- a/hibernate-core/src/main/java/org/hibernate/resource/jdbc/spi/JdbcSessionContext.java
+++ b/hibernate-core/src/main/java/org/hibernate/resource/jdbc/spi/JdbcSessionContext.java
@@ -23,6 +23,8 @@ public interface JdbcSessionContext {
PhysicalConnectionHandlingMode getPhysicalConnectionHandlingMode();
+ boolean doesConnectionProviderDisableAutoCommit();
+
/**
* @deprecated Use {@link #getPhysicalConnectionHandlingMode} instead
*/
diff --git a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorTest.java b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorTest.java
index 8832f662e3..df1646aa58 100644
--- a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/internal/JdbcCoordinatorTest.java
@@ -4,7 +4,6 @@ import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
-import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
@@ -12,7 +11,6 @@ import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
-import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.JdbcSessionOwner;
@@ -70,7 +68,7 @@ public class JdbcCoordinatorTest {
ConfigurationService configurationService = Mockito.mock( ConfigurationService.class );
when( serviceRegistry.getService( eq( ConfigurationService.class ) ) ).thenReturn(
configurationService );
- when( configurationService.getSetting(eq( AvailableSettings.SKIP_AUTOCOMMIT_CHECK ), same( StandardConverters.BOOLEAN), eq( false )) )
+ when( configurationService.getSetting( eq( AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT ), same( StandardConverters.BOOLEAN), eq( false )) )
.thenReturn( false );
SqlExceptionHelper sqlExceptionHelper = Mockito.mock( SqlExceptionHelper.class );
diff --git a/hibernate-core/src/test/java/org/hibernate/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java b/hibernate-core/src/test/java/org/hibernate/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java
index 1e1e71e816..25d256e136 100644
--- a/hibernate-core/src/test/java/org/hibernate/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/test/resource/transaction/jdbc/autocommit/AbstractSkipAutoCommitTest.java
@@ -15,13 +15,9 @@ import javax.persistence.Id;
import javax.sql.DataSource;
import org.hibernate.cfg.AvailableSettings;
-import org.hibernate.cfg.Environment;
-import org.hibernate.dialect.H2Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
-import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.jdbc.PreparedStatementSpyConnectionProvider;
-import org.hibernate.test.util.ReflectionUtil;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
@@ -51,7 +47,7 @@ public abstract class AbstractSkipAutoCommitTest extends BaseEntityManagerFuncti
Map config = super.getConfig();
config.put( AvailableSettings.DATASOURCE, dataSource() );
- config.put( AvailableSettings.SKIP_AUTOCOMMIT_CHECK, Boolean.TRUE );
+ config.put( AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, Boolean.TRUE );
config.put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
return config;
diff --git a/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPSkipAutoCommitTest.java b/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPSkipAutoCommitTest.java
index a3cfc2dbaa..6e2cd63875 100644
--- a/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPSkipAutoCommitTest.java
+++ b/hibernate-hikaricp/src/test/java/org/hibernate/test/hikaricp/HikariCPSkipAutoCommitTest.java
@@ -4,7 +4,7 @@
* 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.test.resource.transaction.jdbc;
+package org.hibernate.test.hikaricp;
import java.sql.Connection;
import java.sql.SQLException;
@@ -40,7 +40,7 @@ public class HikariCPSkipAutoCommitTest extends BaseCoreFunctionalTestCase {
org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,
connectionProvider
);
- configuration.getProperties().put( AvailableSettings.SKIP_AUTOCOMMIT_CHECK, Boolean.TRUE );
+ configuration.getProperties().put( AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, Boolean.TRUE );
configuration.getProperties().put( "hibernate.hikari.autoCommit", Boolean.FALSE.toString() );
}