HHH-14867 Don't forcefully acquire connection for transaction handling

This commit is contained in:
Christian Beikov 2024-02-16 13:48:21 +01:00
parent 897b87bca6
commit 4ac91f793f
17 changed files with 53 additions and 9 deletions

View File

@ -83,7 +83,12 @@ public abstract class AbstractLogicalConnectionImplementor implements LogicalCon
public void commit() {
try {
log.trace( "Preparing to commit transaction via JDBC Connection.commit()" );
getConnectionForTransactionManagement().commit();
if ( isPhysicallyConnected() ) {
getConnectionForTransactionManagement().commit();
}
else {
errorIfClosed();
}
status = TransactionStatus.COMMITTED;
log.trace( "Transaction committed via JDBC Connection.commit()" );
}
@ -118,7 +123,12 @@ public abstract class AbstractLogicalConnectionImplementor implements LogicalCon
public void rollback() {
try {
log.trace( "Preparing to rollback transaction via JDBC Connection.rollback()" );
getConnectionForTransactionManagement().rollback();
if ( isPhysicallyConnected() ) {
getConnectionForTransactionManagement().rollback();
}
else {
errorIfClosed();
}
status = TransactionStatus.ROLLED_BACK;
log.trace( "Transaction rolled-back via JDBC Connection.rollback()" );
}

View File

@ -285,8 +285,7 @@ public class JdbcResourceLocalTransactionCoordinatorImpl implements TransactionC
@Override
public void rollback() {
try {
TransactionStatus status = jdbcResourceTransaction.getStatus();
if ( ( rollbackOnly && status != TransactionStatus.NOT_ACTIVE ) || status == TransactionStatus.ACTIVE ) {
if ( rollbackOnly || jdbcResourceTransaction.getStatus() == TransactionStatus.ACTIVE ) {
jdbcResourceTransaction.rollback();
JdbcResourceLocalTransactionCoordinatorImpl.this.afterCompletionCallback( false );
}

View File

@ -13,9 +13,9 @@ import org.hibernate.stat.Statistics;
import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProvider;
import org.hibernate.testing.orm.jdbc.PreparedStatementSpyConnectionProviderSettingProvider;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.Setting;
import org.hibernate.testing.orm.junit.SettingProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
@ -41,6 +41,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
settingName = AvailableSettings.CONNECTION_PROVIDER,
provider = PreparedStatementSpyConnectionProviderSettingProvider.class)
},
integrationSettings = @Setting(name = AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, value = "true"),
generateStatistics = true
)
@JiraKey( value = "HHH-14867" )
@ -66,7 +67,6 @@ public class L2CacheAccessNoCommitTest {
}
@Test
@FailureExpected
public void test(EntityManagerFactoryScope scope) {
final PreparedStatementSpyConnectionProvider connectionProvider =
(PreparedStatementSpyConnectionProvider) scope.getEntityManagerFactory().getProperties()

View File

@ -61,6 +61,7 @@ public class LazyLoadingConnectionCloseTest extends EntityManagerFactoryBasedFun
);
options.put( AvailableSettings.AUTOCOMMIT, "false" );
options.put( AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, "false" );
connectionProvider = new ConnectionCheckingConnectionProvider();
options.put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );

View File

@ -44,6 +44,8 @@ public class ConnectionsReleaseAutoCommitTest {
connectionProvider.clear();
scope.inTransaction( entityManager -> {
// Force connection acquisition
entityManager.createQuery( "select 1" ).getResultList();
assertEquals( 1, connectionProvider.getTotalOpenedConnectionCount() );
Thing thing = new Thing();
thing.setId( 1 );

View File

@ -66,6 +66,8 @@ public class DisableDiscardPersistenceContextOnCloseTest {
try {
entityManager.getTransaction().begin();
// Force connection acquisition
entityManager.createQuery( "select 1" ).getResultList();
entityManager.persist( wallet );
assertEquals( 1, connectionProvider.getAcquiredConnections().size() );
entityManager.close();

View File

@ -58,6 +58,8 @@ public class EnableDiscardPersistenceContextOnCloseTest {
try {
entityManager.getTransaction().begin();
// Force connection acquisition
entityManager.createQuery( "select 1" ).getResultList();
entityManager.persist( wallet );
assertEquals( 1, connectionProvider.getAcquiredConnections().size() );
entityManager.close();

View File

@ -70,6 +70,8 @@ public class TransactionCommitFailureTest {
try {
em.getTransaction().begin();
// Force connection acquisition
em.createQuery( "select 1" ).getResultList();
transactionFailureTrigger.set( true );
em.getTransaction().commit();
}
@ -92,6 +94,8 @@ public class TransactionCommitFailureTest {
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
// Force connection acquisition
em.createQuery( "select 1" ).getResultList();
assertEquals( true, connectionIsOpen.get() );
transactionFailureTrigger.set( true );
em.getTransaction().rollback();

View File

@ -41,6 +41,7 @@ import static org.junit.jupiter.api.Assertions.fail;
integrationSettings = {
@Setting(name = AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA"),
@Setting(name = AvailableSettings.JPA_TRANSACTION_COMPLIANCE, value = "true"),
@Setting(name = AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, value = "true"),
@Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50")
},
settingProviders = {

View File

@ -42,6 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
integrationSettings = {
@Setting(name = AvailableSettings.JPA_TRANSACTION_TYPE, value = "JTA"),
@Setting(name = AvailableSettings.JPA_TRANSACTION_COMPLIANCE, value = "true"),
@Setting(name = AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, value = "true"),
@Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "50")
},
settingProviders = {

View File

@ -59,6 +59,7 @@ import static org.junit.jupiter.api.Assertions.assertSame;
@Setting(name = AvailableSettings.FLUSH_BEFORE_COMPLETION, value = "true"),
@Setting(name = AvailableSettings.USE_QUERY_CACHE, value = "true"),
@Setting(name = AvailableSettings.CACHE_REGION_PREFIX, value = ""),
@Setting(name = AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT, value = "true"),
@Setting(name = "javax.persistence.transactionType", value = "JTA"),
},

View File

@ -502,6 +502,9 @@ public class UnionSubclassTest extends BaseSessionFactoryFunctionalTest {
// connections.
inTransaction( s1 -> {
// Force connection acquisition
s1.createQuery( "select 1" ).getResultList();
// Transaction used by s1 is already started.
// Assert that the Connection is already physically connected.
assertTrue( s1.getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected() );
@ -520,6 +523,8 @@ public class UnionSubclassTest extends BaseSessionFactoryFunctionalTest {
// for a bulk operation.
inTransaction( s2 -> {
// Force connection acquisition
s2.createQuery( "select 1" ).getResultList();
// Check same assertions for s2 as was done for s1.
assertTrue( s2.getJdbcCoordinator().getLogicalConnection().isPhysicallyConnected() );
assertEquals(

View File

@ -22,6 +22,10 @@ public final class TestingJtaBootstrap {
public static void prepare(Map<String,Object> configValues) {
configValues.put( AvailableSettings.JTA_PLATFORM, TestingJtaPlatformImpl.INSTANCE );
configValues.put( AvailableSettings.CONNECTION_PROVIDER, JtaAwareConnectionProviderImpl.class.getName() );
configValues.put(
AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT,
Boolean.TRUE
);
configValues.put( "javax.persistence.transactionType", "JTA" );
}
@ -29,6 +33,10 @@ public final class TestingJtaBootstrap {
registryBuilder.applySetting( AvailableSettings.TRANSACTION_COORDINATOR_STRATEGY, "jta" );
registryBuilder.applySetting( AvailableSettings.JTA_PLATFORM, TestingJtaPlatformImpl.INSTANCE );
registryBuilder.applySetting( AvailableSettings.CONNECTION_PROVIDER, JtaAwareConnectionProviderImpl.class.getName() );
registryBuilder.applySetting(
AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT,
Boolean.TRUE
);
registryBuilder.applySetting( "javax.persistence.transactionType", "JTA" );
}

View File

@ -84,8 +84,8 @@ public abstract class BaseSessionFactoryFunctionalTest
@Override
public StandardServiceRegistry produceServiceRegistry(StandardServiceRegistryBuilder ssrBuilder) {
ssrBuilder.applySetting( AvailableSettings.HBM2DDL_AUTO, exportSchema() ? "create-drop" : "none" );
ServiceRegistryUtil.applySettings( ssrBuilder );
applySettings( ssrBuilder );
ServiceRegistryUtil.applySettings( ssrBuilder );
return ssrBuilder.build();
}

View File

@ -168,7 +168,6 @@ public class EntityManagerFactoryExtension
integrationSettings.put( PersistentTableStrategy.DROP_ID_TABLES, "true" );
integrationSettings.put( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
integrationSettings.put( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
ServiceRegistryUtil.applySettings( integrationSettings );
for ( int i = 0; i < emfAnn.integrationSettings().length; i++ ) {
final Setting setting = emfAnn.integrationSettings()[i];
integrationSettings.put( setting.name(), setting.value() );
@ -194,6 +193,7 @@ public class EntityManagerFactoryExtension
integrationSettings.put( AvailableSettings.STATEMENT_INSPECTOR, new SQLStatementInspector() );
}
ServiceRegistryUtil.applySettings( integrationSettings );
final EntityManagerFactoryScopeImpl scope = new EntityManagerFactoryScopeImpl( pui, integrationSettings );
locateExtensionStore( testInstance, context ).put( EMF_KEY, scope );

View File

@ -196,12 +196,12 @@ public class ServiceRegistryExtension
ssrb.applySetting( PersistentTableStrategy.DROP_ID_TABLES, "true" );
ssrb.applySetting( GlobalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
ssrb.applySetting( LocalTemporaryTableMutationStrategy.DROP_ID_TABLES, "true" );
ServiceRegistryUtil.applySettings( ssrb.getSettings() );
if ( ssrAnnRef.isPresent() ) {
final ServiceRegistry serviceRegistryAnn = ssrAnnRef.get();
configureServices( serviceRegistryAnn, ssrb );
}
ServiceRegistryUtil.applySettings( ssrb.getSettings() );
return ssrb.build();
}

View File

@ -38,6 +38,10 @@ public class ServiceRegistryUtil {
AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
builder.applySetting(
AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT,
Boolean.TRUE
);
}
return builder;
}
@ -49,6 +53,10 @@ public class ServiceRegistryUtil {
AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
( (Map<Object, Object>) properties ).put(
AvailableSettings.CONNECTION_PROVIDER_DISABLES_AUTOCOMMIT,
Boolean.TRUE
);
}
}