diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java index da124c6fd999..b7c8f430571a 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java @@ -11,7 +11,6 @@ import java.sql.SQLException; import java.util.Map; import java.util.Properties; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -19,11 +18,9 @@ import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.cfg.AvailableSettings; -import org.hibernate.cfg.Environment; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.UnknownUnwrapTypeException; import org.hibernate.service.spi.Configurable; @@ -56,10 +53,9 @@ public class DriverManagerConnectionProviderImpl private boolean active = true; - private ConcurrentLinkedQueue connections = new ConcurrentLinkedQueue(); private ConnectionCreator connectionCreator; private ScheduledExecutorService executorService; - + private PooledConnections pool; // create the pool ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -76,54 +72,16 @@ public void configure(Map configurationValues) { log.usingHibernateBuiltInConnectionPool(); connectionCreator = buildCreator( configurationValues ); + pool = buildPool( configurationValues ); - final int minSize = ConfigurationHelper.getInt( MIN_SIZE, configurationValues, 1 ); - final int maxSize = ConfigurationHelper.getInt( AvailableSettings.POOL_SIZE, configurationValues, 20 ); - final int initialSize = ConfigurationHelper.getInt( INITIAL_SIZE, configurationValues, minSize ); final long validationInterval = ConfigurationHelper.getLong( VALIDATION_INTERVAL, configurationValues, 30 ); - - log.hibernateConnectionPoolSize( maxSize, minSize ); - - log.debugf( "Initializing Connection pool with %s Connections", initialSize ); - for ( int i = 0; i < initialSize; i++ ) { - connections.add( connectionCreator.createConnection() ); - } - executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay( new Runnable() { private boolean primed; @Override public void run() { - int size = connections.size(); - - if ( !primed && size >= minSize ) { - // IMPL NOTE : the purpose of primed is to allow the pool to lazily reach its - // defined min-size. - log.debug( "Connection pool now considered primed; min-size will be maintained" ); - primed = true; - } - - if ( size < minSize && primed ) { - int numberToBeAdded = minSize - size; - log.debugf( "Adding %s Connections to the pool", numberToBeAdded ); - for (int i = 0; i < numberToBeAdded; i++) { - connections.add( connectionCreator.createConnection() ); - } - } - else if ( size > maxSize ) { - int numberToBeRemoved = size - maxSize; - log.debugf( "Removing %s Connections from the pool", numberToBeRemoved ); - for ( int i = 0; i < numberToBeRemoved; i++ ) { - Connection connection = connections.poll(); - try { - connection.close(); - } - catch (SQLException e) { - log.unableToCloseConnection( e ); - } - } - } + pool.validate(); } }, validationInterval, @@ -132,6 +90,27 @@ else if ( size > maxSize ) { ); } + private PooledConnections buildPool(Map configurationValues) { + final boolean autoCommit = ConfigurationHelper.getBoolean( + AvailableSettings.AUTOCOMMIT, + configurationValues, + false + ); + final int minSize = ConfigurationHelper.getInt( MIN_SIZE, configurationValues, 1 ); + final int maxSize = ConfigurationHelper.getInt( AvailableSettings.POOL_SIZE, configurationValues, 20 ); + final int initialSize = ConfigurationHelper.getInt( INITIAL_SIZE, configurationValues, minSize ); + + PooledConnections.Builder pooledConnectionBuilder = new PooledConnections.Builder( + connectionCreator, + autoCommit + ); + pooledConnectionBuilder.initialSize( initialSize ); + pooledConnectionBuilder.minSize( minSize ); + pooledConnectionBuilder.maxSize( maxSize ); + + return pooledConnectionBuilder.build(); + } + private ConnectionCreator buildCreator(Map configurationValues) { final ConnectionCreatorBuilder connectionCreatorBuilder = new ConnectionCreatorBuilder( serviceRegistry ); @@ -206,12 +185,11 @@ public Connection getConnection() throws SQLException { throw new HibernateException( "Connection pool is no longer active" ); } - Connection connection; - if ( (connection = connections.poll()) == null ) { - connection = connectionCreator.createConnection(); + Connection conn = pool.poll(); + if ( conn == null ) { + conn = connectionCreator.createConnection(); } - - return connection; + return conn; } @Override @@ -220,10 +198,9 @@ public void closeConnection(Connection conn) throws SQLException { return; } - this.connections.offer( conn ); + pool.add( conn ); } - @Override public boolean supportsAggressiveRelease() { return false; @@ -265,17 +242,14 @@ public void stop() { } executorService = null; - for ( Connection connection : connections ) { - try { - connection.close(); - } - catch (SQLException e) { - log.unableToClosePooledConnection( e ); - } + try { + pool.close(); + } + catch (SQLException e) { + log.unableToClosePooledConnection( e ); } } - //CHECKSTYLE:START_ALLOW_FINALIZER @Override protected void finalize() throws Throwable { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/PooledConnections.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/PooledConnections.java new file mode 100644 index 000000000000..88a58a54da2f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/PooledConnections.java @@ -0,0 +1,141 @@ +/* + * 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 . + */ +package org.hibernate.engine.jdbc.connections.internal; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; + +/** + * @author Andrea Boriero + */ +public class PooledConnections { + + private ConcurrentLinkedQueue connections = new ConcurrentLinkedQueue(); + + private static final CoreMessageLogger log = CoreLogging.messageLogger( DriverManagerConnectionProviderImpl.class ); + + private final ConnectionCreator connectionCreator; + private final boolean autoCommit; + private final int minSize; + private final int maxSize; + + private boolean primed; + + private PooledConnections( + Builder builder) { + log.debugf( "Initializing Connection pool with %s Connections", builder.initialSize ); + connectionCreator = builder.connectionCreator; + autoCommit = builder.autoCommit; + maxSize = builder.maxSize; + minSize = builder.minSize; + log.hibernateConnectionPoolSize( maxSize, minSize ); + addConnections( builder.initialSize ); + } + + public void validate() { + final int size = size(); + + if ( !primed && size >= minSize ) { + // IMPL NOTE : the purpose of primed is to allow the pool to lazily reach its + // defined min-size. + log.debug( "Connection pool now considered primed; min-size will be maintained" ); + primed = true; + } + + if ( size < minSize && primed ) { + int numberToBeAdded = minSize - size; + log.debugf( "Adding %s Connections to the pool", numberToBeAdded ); + addConnections( numberToBeAdded ); + } + else if ( size > maxSize ) { + int numberToBeRemoved = size - maxSize; + log.debugf( "Removing %s Connections from the pool", numberToBeRemoved ); + removeConnections( numberToBeRemoved ); + } + } + + public void add(Connection conn) throws SQLException { + conn.setAutoCommit( true ); + conn.clearWarnings(); + connections.offer( conn ); + } + + public Connection poll() throws SQLException { + Connection conn = connections.poll(); + if ( conn == null ) { + return null; + } + conn.setAutoCommit( autoCommit ); + return conn; + } + + public void close() throws SQLException { + for ( Connection connection : connections ) { + connection.close(); + } + } + + public int size() { + return connections.size(); + } + + protected void removeConnections(int numberToBeRemoved) { + for ( int i = 0; i < numberToBeRemoved; i++ ) { + Connection connection = connections.poll(); + try { + if ( connection != null ) { + connection.close(); + } + } + catch (SQLException e) { + log.unableToCloseConnection( e ); + } + } + } + + protected void addConnections(int numberOfConnections) { + for ( int i = 0; i < numberOfConnections; i++ ) { + connections.add( connectionCreator.createConnection() ); + } + } + + public static class Builder { + private final ConnectionCreator connectionCreator; + private boolean autoCommit; + private int initialSize = 1; + private int minSize = 1; + private int maxSize = 20; + + public Builder(ConnectionCreator connectionCreator, boolean autoCommit) { + this.connectionCreator = connectionCreator; + this.autoCommit = autoCommit; + } + + public Builder initialSize(int initialSize) { + this.initialSize = initialSize; + return this; + } + + public Builder minSize(int minSize) { + this.minSize = minSize; + return this; + } + + public Builder maxSize(int maxSize) { + this.maxSize = maxSize; + return this; + } + + public PooledConnections build() { + return new PooledConnections( this ); + } + } +}