Use a shared connection provider for most tests to reduce test time significantly

This commit is contained in:
Christian Beikov 2021-02-03 11:23:17 +01:00
parent 709ac039d1
commit 1983123d72
28 changed files with 378 additions and 79 deletions

View File

@ -0,0 +1,28 @@
/*
* 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.engine.jdbc.connections.internal;
import java.sql.Connection;
import java.sql.SQLException;
/**
* Contract for validating JDBC Connections
*
* @author Christian Beikov
*/
public interface ConnectionValidator {
ConnectionValidator ALWAYS_VALID = connection -> true;
/**
* Checks if the connection is still valid
*
* @return <code>true</code> if the connection is valid, <code>false</code> otherwise
* @throws SQLException when an error happens due to the connection usage leading to a connection close
*/
boolean isValid(Connection connection) throws SQLException;
}

View File

@ -47,7 +47,7 @@ import org.hibernate.service.spi.Stoppable;
* @author Steve Ebersole
*/
public class DriverManagerConnectionProviderImpl
implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService {
implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService, ConnectionValidator {
private static final ConnectionPoolingLogger log = ConnectionPoolingLogger.CONNECTIONS_LOGGER;
@ -94,7 +94,7 @@ public class DriverManagerConnectionProviderImpl
pooledConnectionBuilder.initialSize( initialSize );
pooledConnectionBuilder.minSize( minSize );
pooledConnectionBuilder.maxSize( maxSize );
pooledConnectionBuilder.validator( this );
return pooledConnectionBuilder.build();
}
@ -205,6 +205,12 @@ public class DriverManagerConnectionProviderImpl
}
}
protected void validateConnectionsReturned() {
int allocationCount = state.pool.allConnections.size() - state.pool.availableConnections.size();
if ( allocationCount != 0 ) {
log.error( "Connection leak detected: there are " + allocationCount + " unclosed connections!");
}
}
// destroy the pool ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -212,6 +218,7 @@ public class DriverManagerConnectionProviderImpl
public void stop() {
if ( state != null ) {
state.stop();
validateConnectionsReturned();
}
}
@ -234,6 +241,10 @@ public class DriverManagerConnectionProviderImpl
return connectionCreator.getConnectionProperties();
}
@Override
public boolean isValid(Connection connection) throws SQLException {
return true;
}
public static class PooledConnections {
@ -243,6 +254,7 @@ public class DriverManagerConnectionProviderImpl
private static final CoreMessageLogger log = CoreLogging.messageLogger( DriverManagerConnectionProviderImpl.class );
private final ConnectionCreator connectionCreator;
private final ConnectionValidator connectionValidator;
private final boolean autoCommit;
private final int minSize;
private final int maxSize;
@ -253,6 +265,9 @@ public class DriverManagerConnectionProviderImpl
Builder builder) {
log.debugf( "Initializing Connection pool with %s Connections", builder.initialSize );
connectionCreator = builder.connectionCreator;
connectionValidator = builder.connectionValidator == null
? ConnectionValidator.ALWAYS_VALID
: builder.connectionValidator;
autoCommit = builder.autoCommit;
maxSize = builder.maxSize;
minSize = builder.minSize;
@ -283,26 +298,79 @@ public class DriverManagerConnectionProviderImpl
}
public void add(Connection conn) throws SQLException {
conn.setAutoCommit( true );
conn.clearWarnings();
availableConnections.offer( conn );
final Connection connection = releaseConnection( conn );
if ( connection != null ) {
availableConnections.offer( connection );
}
}
protected Connection releaseConnection(Connection conn) {
Exception t = null;
try {
conn.setAutoCommit( true );
conn.clearWarnings();
if ( connectionValidator.isValid( conn ) ) {
return conn;
}
}
catch (SQLException ex) {
t = ex;
}
closeConnection( conn, t );
log.debug( "Connection release failed. Closing pooled connection", t );
return null;
}
public Connection poll() throws SQLException {
Connection conn = availableConnections.poll();
if ( conn == null ) {
synchronized (allConnections) {
if(allConnections.size() < maxSize) {
addConnections( 1 );
return poll();
Connection conn;
do {
conn = availableConnections.poll();
if ( conn == null ) {
synchronized (allConnections) {
if ( allConnections.size() < maxSize ) {
addConnections( 1 );
return poll();
}
}
throw new HibernateException(
"The internal connection pool has reached its maximum size and no connection is currently available!" );
}
throw new HibernateException( "The internal connection pool has reached its maximum size and no connection is currently available!" );
}
conn.setAutoCommit( autoCommit );
conn = prepareConnection( conn );
} while ( conn == null );
return conn;
}
protected Connection prepareConnection(Connection conn) {
Exception t = null;
try {
conn.setAutoCommit( autoCommit );
if ( connectionValidator.isValid( conn ) ) {
return conn;
}
}
catch (SQLException ex) {
t = ex;
}
closeConnection( conn, t );
log.debug( "Connection preparation failed. Closing pooled connection", t );
return null;
}
protected void closeConnection(Connection conn, Throwable t) {
try {
conn.close();
}
catch (SQLException ex) {
log.unableToCloseConnection( ex );
if ( t != null ) {
t.addSuppressed( ex );
}
}
finally {
allConnections.remove( conn );
}
}
public void close() throws SQLException {
try {
int allocationCount = allConnections.size() - availableConnections.size();
@ -350,6 +418,7 @@ public class DriverManagerConnectionProviderImpl
public static class Builder {
private final ConnectionCreator connectionCreator;
private ConnectionValidator connectionValidator;
private boolean autoCommit;
private int initialSize = 1;
private int minSize = 1;
@ -375,6 +444,11 @@ public class DriverManagerConnectionProviderImpl
return this;
}
public Builder validator(ConnectionValidator connectionValidator) {
this.connectionValidator = connectionValidator;
return this;
}
public PooledConnections build() {
return new PooledConnections( this );
}

View File

@ -25,10 +25,15 @@ import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After;
import org.junit.Before;
@ -223,6 +228,14 @@ public abstract class BaseEntityManagerFunctionalTestCase extends BaseUnitTestCa
config.put( AvailableSettings.XML_FILE_NAMES, dds );
}
if ( !config.containsKey( Environment.CONNECTION_PROVIDER ) ) {
config.put( GlobalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
config.put( LocalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
config.put(
AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
}
addConfigOptions( config );
return config;
}

View File

@ -10,6 +10,7 @@ import java.sql.SQLException;
import java.util.Map;
import javax.persistence.EntityManager;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.jpa.test.Wallet;
@ -34,6 +35,7 @@ public class DisableDiscardPersistenceContextOnCloseTest extends BaseEntityManag
@Override
protected Map getConfig() {
Map config = super.getConfig();
connectionProvider.setConnectionProvider( (ConnectionProvider) config.get( org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER ) );
config.put( AvailableSettings.DISCARD_PC_ON_CLOSE, "false");
config.put(
org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,

View File

@ -10,6 +10,7 @@ import java.util.Map;
import javax.persistence.EntityManager;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.jpa.test.Wallet;
@ -35,6 +36,7 @@ public class EnableDiscardPersistenceContextOnCloseTest extends BaseEntityManage
@Override
protected Map getConfig() {
Map config = super.getConfig();
connectionProvider.setConnectionProvider( (ConnectionProvider) config.get( org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER ) );
config.put( AvailableSettings.DISCARD_PC_ON_CLOSE, "true");
config.put(
org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,

View File

@ -25,6 +25,7 @@ import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.TransactionException;
import org.hibernate.dialect.CockroachDB192Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.Oracle10gDialect;
@ -38,6 +39,7 @@ import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
import org.hibernate.testing.transaction.TransactionUtil;
import org.hibernate.testing.util.ExceptionUtil;
import org.jboss.logging.Logger;
@ -56,6 +58,14 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
private static final Logger log = Logger.getLogger( LockTest.class );
@Override
protected void addConfigOptions(Map options) {
super.addConfigOptions( options );
// Looks like Oracle Connections that experience a timeout produce different errors when they timeout again?!
SharedDriverManagerConnectionProviderImpl.getInstance().reset();
options.remove( org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER );
}
@Test
@SkipForDialect( value = CockroachDB192Dialect.class )
public void testFindWithTimeoutHint() {
@ -557,6 +567,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
// ASE15.5 will generate select...holdlock and fail at this test, but ASE15.7 passes it. Skip it for ASE15.5
// only.
@SkipForDialect(value = { SQLServerDialect.class })
@SkipForDialect(DerbyDialect.class)
public void testContendedPessimisticLock() throws Exception {
final CountDownLatch latch = new CountDownLatch( 1 );
final Lock lock = new Lock();
@ -622,7 +633,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean backGroundThreadCompleted = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean backGroundThreadCompleted = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
if ( backGroundThreadCompleted ) {
// the background thread read a value. At the very least we need to assert that he did not see the
@ -646,12 +657,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testContendedPessimisticLock", t, lock.getId() );
}
}
@ -720,7 +726,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -728,17 +734,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testContendedPessimisticReadLockTimeout", t, lock.getId() );
}
}
@ -805,7 +806,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -813,17 +814,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testContendedPessimisticWriteLockTimeout", t, lock.getId() );
}
}
@ -890,7 +886,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -898,17 +894,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testContendedPessimisticWriteLockNoWait", t, lock.getId() );
}
}
@ -980,7 +971,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -988,17 +979,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testQueryTimeout", t, lock.getId() );
}
}
@ -1071,7 +1057,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -1079,17 +1065,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testQueryTimeoutEMProps", t, lock.getId() );
}
}
@ -1157,7 +1138,7 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
try {
t.start();
boolean latchSet = latch.await( 10, TimeUnit.SECONDS ); // should return quickly on success
boolean latchSet = latch.await( 20, TimeUnit.SECONDS ); // should return quickly on success
assertTrue( "background test thread finished (lock timeout is broken)", latchSet );
assertTrue( "background test thread timed out on lock attempt", bgTask.get() );
}
@ -1165,17 +1146,12 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
Thread.interrupted();
}
catch (ExecutionException e) {
fail(e.getMessage());
throw new AssertionError( e );
}
} );
}
finally {
t.join(); // wait for background thread to finish before deleting entity
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lock.getId() );
em.remove( _lock );
} );
awaitThenDelete( "testLockTimeoutEMProps", t, lock.getId() );
}
}
@ -1186,4 +1162,22 @@ public class LockTest extends BaseEntityManagerFunctionalTestCase {
UnversionedLock.class
};
}
private void awaitThenDelete(String test, Thread t, Integer lockId) throws InterruptedException {
// wait for background thread to finish before deleting entity
try {
while ( t.isAlive() ) {
t.join( TimeUnit.SECONDS.toMillis( 30 ) );
final Throwable temp = new Throwable();
temp.setStackTrace( t.getStackTrace() );
log.info( test + ": Thread seems stuck", temp );
t.interrupt();
}
} finally {
doInJPA( this::entityManagerFactory, em -> {
Lock _lock = em.getReference( Lock.class, lockId );
em.remove( _lock );
} );
}
}
}

View File

@ -12,7 +12,9 @@ import java.util.HashMap;
import java.util.Map;
import javax.persistence.LockModeType;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.CockroachDB192Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
import org.hibernate.testing.DialectChecks;
@ -42,6 +44,7 @@ public class StatementIsClosedAfterALockExceptionTest extends BaseEntityManagerF
@Override
protected Map getConfig() {
Map config = super.getConfig();
CONNECTION_PROVIDER.setConnectionProvider( (ConnectionProvider) config.get( AvailableSettings.CONNECTION_PROVIDER ) );
config.put(
org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,
CONNECTION_PROVIDER

View File

@ -38,6 +38,7 @@ import org.hibernate.criterion.Subqueries;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseASE15Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.exception.SQLGrammarException;
import org.hibernate.internal.util.SerializationHelper;
import org.hibernate.transform.Transformers;
@ -92,6 +93,7 @@ public class CriteriaQueryTest extends BaseNonConfigCoreFunctionalTestCase {
);
settings.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -6,6 +6,7 @@ import java.util.Map;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
@ -39,6 +40,7 @@ abstract class BaseInsertOrderingTest extends BaseNonConfigCoreFunctionalTestCas
protected void addSettings(Map settings) {
settings.put( Environment.ORDER_INSERTS, "true" );
settings.put( Environment.STATEMENT_BATCH_SIZE, "10" );
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
}

View File

@ -16,6 +16,7 @@ import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -45,6 +46,7 @@ public class SessionJdbcBatchTest
@Override
protected void addSettings(Map settings) {
settings.put( AvailableSettings.STATEMENT_BATCH_SIZE, 2 );
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -12,6 +12,7 @@ import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -40,6 +41,7 @@ public class JPALockTest extends AbstractJPATest {
public void configure(Configuration cfg) {
super.configure( cfg );
if( SQLServerDialect.class.isAssignableFrom( DIALECT.getClass() )) {
connectionProvider.setConnectionProvider( (ConnectionProvider) cfg.getProperties().get( AvailableSettings.CONNECTION_PROVIDER ) );
cfg.getProperties().put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
}
}

View File

@ -16,6 +16,7 @@ import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.MariaDBDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -37,14 +38,24 @@ import static org.junit.Assert.fail;
*/
@RequiresDialectFeature(DialectChecks.SupportNoWait.class)
public class LockExceptionTests extends AbstractJPATest {
private SQLServerSnapshotIsolationConnectionProvider connectionProvider = new SQLServerSnapshotIsolationConnectionProvider();
@Override
public void configure(Configuration cfg) {
super.configure( cfg );
if( SQLServerDialect.class.isAssignableFrom( DIALECT.getClass() )) {
cfg.getProperties().put( AvailableSettings.CONNECTION_PROVIDER, new SQLServerSnapshotIsolationConnectionProvider() );
connectionProvider.setConnectionProvider( (ConnectionProvider) cfg.getProperties().get( AvailableSettings.CONNECTION_PROVIDER ) );
cfg.getProperties().put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
}
}
@Override
protected void releaseSessionFactory() {
super.releaseSessionFactory();
connectionProvider.stop();
}
@Test
@TestForIssue( jiraKey = "HHH-8786" )
public void testLockTimeoutFind() {

View File

@ -17,6 +17,7 @@ import org.hibernate.Transaction;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.exception.SQLGrammarException;
import org.hibernate.test.jpa.AbstractJPATest;
import org.hibernate.test.jpa.Item;
@ -44,6 +45,7 @@ public class RepeatableReadTest extends AbstractJPATest {
public void configure(Configuration cfg) {
super.configure( cfg );
if( SQLServerDialect.class.isAssignableFrom( DIALECT.getClass() )) {
connectionProvider.setConnectionProvider( (ConnectionProvider) cfg.getProperties().get( AvailableSettings.CONNECTION_PROVIDER ) );
cfg.getProperties().put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
}
}

View File

@ -15,6 +15,7 @@ import javax.persistence.QueryHint;
import javax.persistence.Table;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.jpa.QueryHints;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
@ -48,6 +49,7 @@ public class QueryTimeOutTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void addSettings(Map settings) {
CONNECTION_PROVIDER.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put( AvailableSettings.CONNECTION_PROVIDER, CONNECTION_PROVIDER );
}

View File

@ -22,6 +22,7 @@ import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -62,6 +63,7 @@ public class JdbcTimeCustomTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -15,6 +15,7 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -49,6 +50,7 @@ public class JdbcTimeDefaultTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -19,6 +19,7 @@ import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -59,6 +60,7 @@ public class JdbcTimestampCustomSessionLevelTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -19,6 +19,7 @@ import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -59,6 +60,7 @@ public class JdbcTimestampCustomTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -14,6 +14,7 @@ import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
@ -47,6 +48,7 @@ public class JdbcTimestampDefaultTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -11,6 +11,7 @@ import java.util.TimeZone;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.test.util.jdbc.TimeZoneConnectionProvider;
@ -29,6 +30,7 @@ public class JdbcTimestampUTCTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -10,6 +10,7 @@ import java.util.Map;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.test.util.jdbc.TimeZoneConnectionProvider;
@ -26,6 +27,7 @@ public class JdbcTimestampWithDefaultUTCTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -18,6 +18,7 @@ import javax.persistence.Id;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.CockroachDB192Dialect;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.SkipForDialect;
@ -47,6 +48,7 @@ public class JdbcTimestampWithoutUTCTimeZoneTest
@Override
protected void addSettings(Map settings) {
connectionProvider.setConnectionProvider( (ConnectionProvider) settings.get( AvailableSettings.CONNECTION_PROVIDER ) );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
connectionProvider

View File

@ -23,6 +23,7 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Order;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.jdbc.Work;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
@ -56,6 +57,7 @@ public class UnionSubclassTest extends BaseCoreFunctionalTestCase {
public void configure(Configuration cfg) {
super.configure( cfg );
if( SQLServerDialect.class.isAssignableFrom( DIALECT.getClass() )) {
connectionProvider.setConnectionProvider( (ConnectionProvider) cfg.getProperties().get( AvailableSettings.CONNECTION_PROVIDER ) );
cfg.getProperties().put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
}
}

View File

@ -16,6 +16,7 @@ import javax.transaction.SystemException;
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -25,6 +26,8 @@ import org.hibernate.envers.AuditReader;
import org.hibernate.envers.AuditReaderFactory;
import org.hibernate.envers.boot.internal.EnversIntegrator;
import org.hibernate.envers.configuration.EnversSettings;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
@ -33,6 +36,7 @@ import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter;
import org.hibernate.testing.AfterClassOnce;
import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit4.Helper;
import org.jboss.logging.Logger;
@ -139,6 +143,14 @@ public abstract class BaseEnversJPAFunctionalTestCase extends AbstractEnversTest
config.put( AvailableSettings.XML_FILE_NAMES, dds );
}
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
config.put( GlobalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
config.put( LocalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
config.put(
org.hibernate.cfg.AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
}
addConfigOptions( config );
return config;

View File

@ -34,6 +34,7 @@ public class ConnectionProviderDelegate implements
private ServiceRegistryImplementor serviceRegistry;
private ConnectionProvider connectionProvider;
private boolean configured;
public ConnectionProviderDelegate() {
}
@ -42,6 +43,14 @@ public class ConnectionProviderDelegate implements
this.connectionProvider = connectionProvider;
}
public ConnectionProvider getConnectionProvider() {
return connectionProvider;
}
public void setConnectionProvider(ConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
}
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
this.serviceRegistry = serviceRegistry;
@ -49,18 +58,21 @@ public class ConnectionProviderDelegate implements
@Override
public void configure(Map configurationValues) {
if ( connectionProvider == null ) {
@SuppressWarnings("unchecked")
Map<String, Object> settings = new HashMap<>( configurationValues );
settings.remove( AvailableSettings.CONNECTION_PROVIDER );
connectionProvider = ConnectionProviderInitiator.INSTANCE.initiateService(
settings,
serviceRegistry
);
if ( !configured ) {
if ( connectionProvider == null ) {
@SuppressWarnings("unchecked")
Map<String, Object> settings = new HashMap<>( configurationValues );
settings.remove( AvailableSettings.CONNECTION_PROVIDER );
connectionProvider = ConnectionProviderInitiator.INSTANCE.initiateService(
settings,
serviceRegistry
);
}
if ( connectionProvider instanceof Configurable ) {
Configurable configurableConnectionProvider = (Configurable) connectionProvider;
configurableConnectionProvider.configure( settings );
configurableConnectionProvider.configure( configurationValues );
}
configured = true;
}
}

View File

@ -0,0 +1,95 @@
/*
* 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.testing.jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
import org.hibernate.internal.util.config.ConfigurationHelper;
/**
* A special connection provider that is shared across test runs for better performance.
*
* @author Christian Beikov
*/
public class SharedDriverManagerConnectionProviderImpl extends DriverManagerConnectionProviderImpl {
private static final SharedDriverManagerConnectionProviderImpl INSTANCE = new SharedDriverManagerConnectionProviderImpl();
public static SharedDriverManagerConnectionProviderImpl getInstance() {
return INSTANCE;
}
private Config config;
@Override
public void configure(Map configurationValues) {
final Config c = new Config( configurationValues );
if ( !c.isCompatible( config ) ) {
if ( config != null ) {
super.stop();
}
super.configure( configurationValues );
config = c;
}
}
@Override
public boolean isValid(Connection connection) throws SQLException {
// Wait at most 5 seconds to validate a connection is still valid
return connection.isValid( 5 );
}
@Override
public void stop() {
// No need to stop as this is a shared instance
validateConnectionsReturned();
}
public void reset() {
super.stop();
config = null;
}
private static class Config {
private final boolean autoCommit;
private final int minSize;
private final int maxSize;
private final int initialSize;
private final String driverClassName;
private final String url;
private final Properties connectionProps;
private final Integer isolation;
public Config(Map configurationValues) {
this.autoCommit = ConfigurationHelper.getBoolean( AvailableSettings.AUTOCOMMIT, configurationValues, false );
this.minSize = ConfigurationHelper.getInt( MIN_SIZE, configurationValues, 2 );
this.maxSize = ConfigurationHelper.getInt( AvailableSettings.POOL_SIZE, configurationValues, 20 );
this.initialSize = ConfigurationHelper.getInt( INITIAL_SIZE, configurationValues, minSize );
this.driverClassName = (String) configurationValues.get( AvailableSettings.DRIVER );
this.url = (String) configurationValues.get( AvailableSettings.URL );
this.connectionProps = ConnectionProviderInitiator.getConnectionProperties( configurationValues );
this.isolation = ConnectionProviderInitiator.extractIsolation( configurationValues );
}
boolean isCompatible(Config config) {
return config != null && autoCommit == config.autoCommit && minSize == config.minSize
&& maxSize == config.maxSize && initialSize == config.initialSize
&& driverClassName.equals( config.driverClassName )
&& url.equals( config.url )
&& connectionProps.equals( config.connectionProps )
&& Objects.equals( isolation, config.isolation );
}
}
}

View File

@ -34,6 +34,8 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
import org.hibernate.internal.build.AllowSysOut;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
@ -48,6 +50,7 @@ import org.hibernate.testing.OnExpectedFailure;
import org.hibernate.testing.OnFailure;
import org.hibernate.testing.SkipLog;
import org.hibernate.testing.cache.CachingRegionFactory;
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
import org.hibernate.testing.transaction.TransactionUtil2;
import org.junit.After;
import org.junit.Before;
@ -176,6 +179,14 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase {
}
configuration.setImplicitNamingStrategy( ImplicitNamingStrategyLegacyJpaImpl.INSTANCE );
configuration.setProperty( Environment.DIALECT, getDialect().getClass().getName() );
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
configuration.getProperties().put( GlobalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
configuration.getProperties().put( LocalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
configuration.getProperties().put(
AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
}
return configuration;
}

View File

@ -33,11 +33,14 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
import org.hibernate.internal.build.AllowPrintStacktrace;
import org.hibernate.internal.build.AllowSysOut;
import org.hibernate.internal.util.ReflectHelper;
@ -58,6 +61,7 @@ import org.hibernate.testing.BeforeClassOnce;
import org.hibernate.testing.OnExpectedFailure;
import org.hibernate.testing.OnFailure;
import org.hibernate.testing.cache.CachingRegionFactory;
import org.hibernate.testing.jdbc.SharedDriverManagerConnectionProviderImpl;
import org.hibernate.testing.transaction.TransactionUtil2;
import org.junit.After;
import org.junit.Before;
@ -175,6 +179,14 @@ public class BaseNonConfigCoreFunctionalTestCase extends BaseUnitTestCase {
afterBootstrapServiceRegistryBuilt( bsr );
final Map settings = new HashMap();
if ( !Environment.getProperties().containsKey( Environment.CONNECTION_PROVIDER ) ) {
settings.put( GlobalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
settings.put( LocalTemporaryTableBulkIdStrategy.DROP_ID_TABLES, "true" );
settings.put(
AvailableSettings.CONNECTION_PROVIDER,
SharedDriverManagerConnectionProviderImpl.getInstance()
);
}
addSettings( settings );
final StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder( bsr );