HHH-14432 Implement cleanup for EntityManagerFactoryBuilderImpl to close connections on bootstrap errors

This commit is contained in:
Christian Beikov 2021-02-03 11:18:36 +01:00
parent 21c89240d0
commit 9f460e1c30
2 changed files with 40 additions and 11 deletions

View File

@ -54,6 +54,7 @@ import org.hibernate.bytecode.enhance.spi.UnloadedField;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
import org.hibernate.integrator.spi.Integrator;
@ -77,7 +78,9 @@ import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.secure.spi.GrantedPermission;
import org.hibernate.secure.spi.JaccPermissionDeclarations;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.spi.ServiceBinding;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.service.spi.Stoppable;
import org.hibernate.tool.schema.spi.DelayedDropRegistryNotAvailableImpl;
import org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator;
@ -1213,9 +1216,24 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
@Override
public void cancel() {
cleanup();
// todo : close the bootstrap registry (not critical, but nice to do)
}
private void cleanup() {
// Stop and de-register the ConnectionProvider to prevent connections lying around
if ( standardServiceRegistry instanceof ServiceRegistryImplementor &&
standardServiceRegistry instanceof ServiceBinding.ServiceLifecycleOwner ) {
final ServiceRegistryImplementor serviceRegistry = (ServiceRegistryImplementor) standardServiceRegistry;
final ServiceBinding.ServiceLifecycleOwner lifecycleOwner = (ServiceBinding.ServiceLifecycleOwner) serviceRegistry;
final ServiceBinding<ConnectionProvider> binding = serviceRegistry.locateServiceBinding( ConnectionProvider.class );
if ( binding != null && binding.getService() instanceof Stoppable ) {
lifecycleOwner.stopService( binding );
binding.setService( null );
}
}
}
/**
* Used by extensions : Hibernate Reactive
*/
@ -1245,21 +1263,32 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
catch (Exception e) {
throw persistenceException( "Error performing schema management", e );
}
// release this builder
cancel();
finally {
// release this builder
cancel();
}
}
@Override
public EntityManagerFactory build() {
final SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
populateSfBuilder( sfBuilder, standardServiceRegistry );
boolean success = false;
try {
return sfBuilder.build();
final SessionFactoryBuilder sfBuilder = metadata().getSessionFactoryBuilder();
populateSfBuilder( sfBuilder, standardServiceRegistry );
try {
final EntityManagerFactory emf = sfBuilder.build();
success = true;
return emf;
}
catch (Exception e) {
throw persistenceException( "Unable to build Hibernate SessionFactory", e );
}
}
catch (Exception e) {
throw persistenceException( "Unable to build Hibernate SessionFactory", e );
finally {
if ( !success ) {
cleanup();
}
}
}

View File

@ -29,8 +29,8 @@ public class DdlTransactionIsolatorJtaImpl implements DdlTransactionIsolator {
private final JdbcContext jdbcContext;
private Transaction suspendedTransaction;
private Connection jdbcConnection;
private final Transaction suspendedTransaction;
private final Connection jdbcConnection;
public DdlTransactionIsolatorJtaImpl(JdbcContext jdbcContext) {
this.jdbcContext = jdbcContext;