HHH-14541 Only mark the session factory as closed *after* SessionFactoryObserver#sessionFactoryClosing was called

This commit is contained in:
Yoann Rodière 2021-04-30 14:42:05 +02:00 committed by Andrea Boriero
parent 7f152c36f7
commit eb4e397a04
1 changed files with 47 additions and 32 deletions

View File

@ -160,7 +160,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
private final String name; private final String name;
private final String uuid; private final String uuid;
private transient volatile boolean isClosed; private transient volatile Status status = Status.OPEN;
private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain(); private final transient SessionFactoryObserverChain observer = new SessionFactoryObserverChain();
@ -535,7 +535,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
} }
protected void validateNotClosed() { protected void validateNotClosed() {
if ( isClosed ) { if ( Status.CLOSED == status ) {
throw new IllegalStateException( "EntityManagerFactory is closed" ); throw new IllegalStateException( "EntityManagerFactory is closed" );
} }
} }
@ -625,7 +625,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
} }
private <K,V> Session buildEntityManager(final SynchronizationType synchronizationType, final Map<K,V> map) { private <K,V> Session buildEntityManager(final SynchronizationType synchronizationType, final Map<K,V> map) {
assert !isClosed; assert Status.CLOSED != status;
SessionBuilderImplementor builder = withOptions(); SessionBuilderImplementor builder = withOptions();
if ( synchronizationType == SynchronizationType.SYNCHRONIZED ) { if ( synchronizationType == SynchronizationType.SYNCHRONIZED ) {
@ -694,7 +694,7 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
@Override @Override
public boolean isOpen() { public boolean isOpen() {
return !isClosed; return Status.CLOSED != status;
} }
@Override @Override
@ -789,9 +789,10 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
* collector release the memory. * collector release the memory.
* @throws HibernateException * @throws HibernateException
*/ */
@Override
public void close() throws HibernateException { public void close() throws HibernateException {
synchronized (this) { synchronized (this) {
if ( isClosed ) { if ( Status.OPEN != status ) {
if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) { if ( getSessionFactoryOptions().getJpaCompliance().isJpaClosedComplianceEnabled() ) {
throw new IllegalStateException( "EntityManagerFactory is already closed" ); throw new IllegalStateException( "EntityManagerFactory is already closed" );
} }
@ -800,40 +801,48 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return; return;
} }
isClosed = true; status = Status.CLOSING;
} }
LOG.closing(); try {
observer.sessionFactoryClosing( this ); LOG.closing();
observer.sessionFactoryClosing( this );
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
// a failed attempt to create the SessionFactory // a failed attempt to create the SessionFactory
if ( cacheAccess != null ) { if ( cacheAccess != null ) {
cacheAccess.close(); cacheAccess.close();
}
if ( metamodel != null ) {
metamodel.close();
}
if ( queryPlanCache != null ) {
queryPlanCache.cleanup();
}
if ( delayedDropAction != null ) {
delayedDropAction.perform( serviceRegistry );
}
SessionFactoryRegistry.INSTANCE.removeSessionFactory(
getUuid(),
name,
settings.isSessionFactoryNameAlsoJndiName(),
serviceRegistry.getService( JndiService.class )
);
} }
finally {
if ( metamodel != null ) { status = Status.CLOSED;
metamodel.close();
} }
if ( queryPlanCache != null ) {
queryPlanCache.cleanup();
}
if ( delayedDropAction != null ) {
delayedDropAction.perform( serviceRegistry );
}
SessionFactoryRegistry.INSTANCE.removeSessionFactory(
getUuid(),
name,
settings.isSessionFactoryNameAlsoJndiName(),
serviceRegistry.getService( JndiService.class )
);
observer.sessionFactoryClosed( this ); observer.sessionFactoryClosed( this );
serviceRegistry.destroy(); serviceRegistry.destroy();
} }
@ -977,8 +986,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
getMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor<T>) entityGraph ); getMetamodel().addNamedEntityGraph( graphName, (RootGraphImplementor<T>) entityGraph );
} }
@Override
public boolean isClosed() { public boolean isClosed() {
return isClosed; return Status.CLOSED == status;
} }
private transient StatisticsImplementor statistics; private transient StatisticsImplementor statistics;
@ -1688,4 +1698,9 @@ public class SessionFactoryImpl implements SessionFactoryImplementor {
return this.fastSessionServices; return this.fastSessionServices;
} }
private enum Status {
OPEN,
CLOSING,
CLOSED;
}
} }