HHH-10104 - Fix HHH-10104 Using JPA 2.1 schema generation together with hbm2ddl runs into deadlock with MySQL
This commit is contained in:
parent
076ee5f026
commit
4ff1dcbfa7
|
@ -11,7 +11,6 @@ import java.sql.Driver;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -19,11 +18,9 @@ import java.util.concurrent.TimeUnit;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.cfg.Environment;
|
|
||||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.util.ReflectHelper;
|
|
||||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||||
import org.hibernate.service.UnknownUnwrapTypeException;
|
import org.hibernate.service.UnknownUnwrapTypeException;
|
||||||
import org.hibernate.service.spi.Configurable;
|
import org.hibernate.service.spi.Configurable;
|
||||||
|
@ -56,10 +53,9 @@ public class DriverManagerConnectionProviderImpl
|
||||||
|
|
||||||
private boolean active = true;
|
private boolean active = true;
|
||||||
|
|
||||||
private ConcurrentLinkedQueue<Connection> connections = new ConcurrentLinkedQueue<Connection>();
|
|
||||||
private ConnectionCreator connectionCreator;
|
private ConnectionCreator connectionCreator;
|
||||||
private ScheduledExecutorService executorService;
|
private ScheduledExecutorService executorService;
|
||||||
|
private PooledConnections pool;
|
||||||
|
|
||||||
|
|
||||||
// create the pool ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// create the pool ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -76,54 +72,16 @@ public class DriverManagerConnectionProviderImpl
|
||||||
log.usingHibernateBuiltInConnectionPool();
|
log.usingHibernateBuiltInConnectionPool();
|
||||||
|
|
||||||
connectionCreator = buildCreator( configurationValues );
|
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 );
|
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 = Executors.newSingleThreadScheduledExecutor();
|
||||||
executorService.scheduleWithFixedDelay(
|
executorService.scheduleWithFixedDelay(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
private boolean primed;
|
private boolean primed;
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
int size = connections.size();
|
pool.validate();
|
||||||
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validationInterval,
|
validationInterval,
|
||||||
|
@ -132,6 +90,27 @@ public class DriverManagerConnectionProviderImpl
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
private ConnectionCreator buildCreator(Map configurationValues) {
|
||||||
final ConnectionCreatorBuilder connectionCreatorBuilder = new ConnectionCreatorBuilder( serviceRegistry );
|
final ConnectionCreatorBuilder connectionCreatorBuilder = new ConnectionCreatorBuilder( serviceRegistry );
|
||||||
|
|
||||||
|
@ -206,12 +185,11 @@ public class DriverManagerConnectionProviderImpl
|
||||||
throw new HibernateException( "Connection pool is no longer active" );
|
throw new HibernateException( "Connection pool is no longer active" );
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection connection;
|
Connection conn = pool.poll();
|
||||||
if ( (connection = connections.poll()) == null ) {
|
if ( conn == null ) {
|
||||||
connection = connectionCreator.createConnection();
|
conn = connectionCreator.createConnection();
|
||||||
}
|
}
|
||||||
|
return conn;
|
||||||
return connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -220,10 +198,9 @@ public class DriverManagerConnectionProviderImpl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connections.offer( conn );
|
pool.add( conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsAggressiveRelease() {
|
public boolean supportsAggressiveRelease() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -265,17 +242,14 @@ public class DriverManagerConnectionProviderImpl
|
||||||
}
|
}
|
||||||
executorService = null;
|
executorService = null;
|
||||||
|
|
||||||
for ( Connection connection : connections ) {
|
try {
|
||||||
try {
|
pool.close();
|
||||||
connection.close();
|
}
|
||||||
}
|
catch (SQLException e) {
|
||||||
catch (SQLException e) {
|
log.unableToClosePooledConnection( e );
|
||||||
log.unableToClosePooledConnection( e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//CHECKSTYLE:START_ALLOW_FINALIZER
|
//CHECKSTYLE:START_ALLOW_FINALIZER
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
|
|
|
@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
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<Connection> connections = new ConcurrentLinkedQueue<Connection>();
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue