HHH-12558 Lazy load entity loaders for the less common lock modes

This commit is contained in:
Guillaume Smet 2018-05-09 14:36:59 +02:00 committed by Steve Ebersole
parent d5d68dcec5
commit 98cab7aefb
1 changed files with 51 additions and 55 deletions

View File

@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
@ -236,7 +237,9 @@ public abstract class AbstractEntityPersister
private final Map uniqueKeyLoaders = new HashMap(); private final Map uniqueKeyLoaders = new HashMap();
private final Map lockers = new HashMap(); private final Map lockers = new HashMap();
private final Map loaders = new HashMap(); private UniqueEntityLoader noneLockLoader;
private UniqueEntityLoader readLockLoader;
private final Map<Object, UniqueEntityLoader> loaders = new ConcurrentHashMap<>();
// SQL strings // SQL strings
private String sqlVersionSelectString; private String sqlVersionSelectString;
@ -4117,61 +4120,14 @@ public abstract class AbstractEntityPersister
//Relational based Persisters should be content with this implementation //Relational based Persisters should be content with this implementation
protected void createLoaders() { protected void createLoaders() {
// We load the entity loaders for the most common lock modes.
noneLockLoader = createEntityLoader( LockMode.NONE );
readLockLoader = createEntityLoader( LockMode.READ );
final Map loaders = getLoaders(); final Map loaders = getLoaders();
loaders.put( LockMode.NONE, createEntityLoader( LockMode.NONE ) );
UniqueEntityLoader readLoader = createEntityLoader( LockMode.READ ); // The loaders for the other lock modes are lazily loaded and will later be stored in this map.
loaders.put( LockMode.READ, readLoader );
//TODO: inexact, what we really need to know is: are any outer joins used?
boolean disableForUpdate = getSubclassTableSpan() > 1 &&
hasSubclasses() &&
!getFactory().getDialect().supportsOuterJoinForUpdate();
loaders.put(
LockMode.UPGRADE,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.UPGRADE )
);
loaders.put(
LockMode.UPGRADE_NOWAIT,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.UPGRADE_NOWAIT )
);
loaders.put(
LockMode.UPGRADE_SKIPLOCKED,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.UPGRADE_SKIPLOCKED )
);
loaders.put(
LockMode.FORCE,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.FORCE )
);
loaders.put(
LockMode.PESSIMISTIC_READ,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.PESSIMISTIC_READ )
);
loaders.put(
LockMode.PESSIMISTIC_WRITE,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.PESSIMISTIC_WRITE )
);
loaders.put(
LockMode.PESSIMISTIC_FORCE_INCREMENT,
disableForUpdate ?
readLoader :
createEntityLoader( LockMode.PESSIMISTIC_FORCE_INCREMENT )
);
loaders.put( LockMode.OPTIMISTIC, createEntityLoader( LockMode.OPTIMISTIC ) );
loaders.put( LockMode.OPTIMISTIC_FORCE_INCREMENT, createEntityLoader( LockMode.OPTIMISTIC_FORCE_INCREMENT ) );
loaders.put( loaders.put(
"merge", "merge",
@ -4183,6 +4139,46 @@ public abstract class AbstractEntityPersister
); );
} }
private UniqueEntityLoader getLoaderByLockMode(LockMode lockMode) {
if ( LockMode.NONE == lockMode ) {
return noneLockLoader;
}
else if ( LockMode.READ == lockMode ) {
return readLockLoader;
}
return loaders.computeIfAbsent( lockMode, this::createLazyLoadedEntityLoader );
}
private UniqueEntityLoader createLazyLoadedEntityLoader(Object lockModeObject) {
// Unfortunately, the loaders map mixes LockModes and Strings as keys so we need to accept an Object.
// The cast is safe as we will always call this method with a LockMode.
LockMode lockMode = (LockMode) lockModeObject;
switch ( lockMode ) {
case NONE:
case READ:
case OPTIMISTIC:
case OPTIMISTIC_FORCE_INCREMENT:
return createEntityLoader( lockMode );
case UPGRADE:
case UPGRADE_NOWAIT:
case UPGRADE_SKIPLOCKED:
case FORCE:
case PESSIMISTIC_READ:
case PESSIMISTIC_WRITE:
case PESSIMISTIC_FORCE_INCREMENT:
//TODO: inexact, what we really need to know is: are any outer joins used?
boolean disableForUpdate = getSubclassTableSpan() > 1 &&
hasSubclasses() &&
!getFactory().getDialect().supportsOuterJoinForUpdate();
return disableForUpdate ? readLockLoader : createEntityLoader( lockMode );
default:
throw new IllegalStateException( String.format( "Lock mode %1$s not supported by entity loaders.", lockMode ) );
}
}
protected void createQueryLoader() { protected void createQueryLoader() {
if ( loaderName != null ) { if ( loaderName != null ) {
queryLoader = new NamedQueryLoader( loaderName, this ); queryLoader = new NamedQueryLoader( loaderName, this );
@ -4276,7 +4272,7 @@ public abstract class AbstractEntityPersister
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() ); return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
} }
else { else {
return (UniqueEntityLoader) getLoaders().get( lockOptions.getLockMode() ); return (UniqueEntityLoader) getLoaderByLockMode( lockOptions.getLockMode() );
} }
} }