HHH-12915 - Concurrency issue within org.hibernate.internal.SessionFactoryImpl

This commit is contained in:
Vlad Mihalcea 2018-08-21 17:45:58 +03:00
parent 710662200b
commit 9f1fde7127
1 changed files with 13 additions and 14 deletions

View File

@ -157,7 +157,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
private final String name; private final String name;
private final String uuid; private final String uuid;
private transient boolean isClosed; private transient volatile boolean isClosed;
private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain(); private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain();
@ -166,7 +166,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient Map<String,Object> properties; private final transient Map<String,Object> properties;
private final transient SessionFactoryServiceRegistry serviceRegistry; private final transient SessionFactoryServiceRegistry serviceRegistry;
private transient JdbcServices jdbcServices; private final transient JdbcServices jdbcServices;
private final transient SQLFunctionRegistry sqlFunctionRegistry; private final transient SQLFunctionRegistry sqlFunctionRegistry;
@ -181,7 +181,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
private final transient CurrentSessionContext currentSessionContext; private final transient CurrentSessionContext currentSessionContext;
private DelayedDropAction delayedDropAction; private volatile DelayedDropAction delayedDropAction;
// todo : move to MetamodelImpl // todo : move to MetamodelImpl
private final transient Map<String,IdentifierGenerator> identifierGenerators; private final transient Map<String,IdentifierGenerator> identifierGenerators;
@ -219,7 +219,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
this.name = sfName; this.name = sfName;
this.uuid = options.getUuid(); this.uuid = options.getUuid();
final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class ); jdbcServices = serviceRegistry.getService( JdbcServices.class );
this.properties = new HashMap<>(); this.properties = new HashMap<>();
this.properties.putAll( serviceRegistry.getService( ConfigurationService.class ).getSettings() ); this.properties.putAll( serviceRegistry.getService( ConfigurationService.class ).getSettings() );
@ -544,9 +544,6 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
@Override @Override
public JdbcServices getJdbcServices() { public JdbcServices getJdbcServices() {
if ( jdbcServices == null ) {
jdbcServices = getServiceRegistry().getService( JdbcServices.class );
}
return jdbcServices; return jdbcServices;
} }
@ -780,6 +777,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
public void close() throws HibernateException { public void close() throws HibernateException {
//This is an idempotent operation so we can do it even before the checks (it won't hurt): //This is an idempotent operation so we can do it even before the checks (it won't hurt):
Environment.getBytecodeProvider().resetCaches(); Environment.getBytecodeProvider().resetCaches();
synchronized (this) {
if ( isClosed ) { if ( isClosed ) {
if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) { if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) {
throw new IllegalStateException( "EntityManagerFactory is already closed" ); throw new IllegalStateException( "EntityManagerFactory is already closed" );
@ -789,11 +787,12 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
return; return;
} }
isClosed = true;
}
LOG.closing(); LOG.closing();
observer.sessionFactoryClosing( this ); observer.sessionFactoryClosing( this );
isClosed = true;
settings.getMultiTableBulkIdStrategy().release( serviceRegistry.getService( JdbcServices.class ), buildLocalConnectionAccess() ); settings.getMultiTableBulkIdStrategy().release( serviceRegistry.getService( JdbcServices.class ), buildLocalConnectionAccess() );
// NOTE : the null checks below handle cases where close is called from // NOTE : the null checks below handle cases where close is called from