Skip to content

Commit 98cab7a

Browse files
gsmetsebersole
authored andcommitted
HHH-12558 Lazy load entity loaders for the less common lock modes
1 parent d5d68dc commit 98cab7a

File tree

1 file changed

+50
-54
lines changed

1 file changed

+50
-54
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Set;
24+
import java.util.concurrent.ConcurrentHashMap;
2425

2526
import org.hibernate.AssertionFailure;
2627
import org.hibernate.EntityMode;
@@ -236,7 +237,9 @@ public abstract class AbstractEntityPersister
236237

237238
private final Map uniqueKeyLoaders = new HashMap();
238239
private final Map lockers = new HashMap();
239-
private final Map loaders = new HashMap();
240+
private UniqueEntityLoader noneLockLoader;
241+
private UniqueEntityLoader readLockLoader;
242+
private final Map<Object, UniqueEntityLoader> loaders = new ConcurrentHashMap<>();
240243

241244
// SQL strings
242245
private String sqlVersionSelectString;
@@ -4117,61 +4120,14 @@ protected Map getLoaders() {
41174120

41184121
//Relational based Persisters should be content with this implementation
41194122
protected void createLoaders() {
4120-
final Map loaders = getLoaders();
4121-
loaders.put( LockMode.NONE, createEntityLoader( LockMode.NONE ) );
4123+
// We load the entity loaders for the most common lock modes.
41224124

4123-
UniqueEntityLoader readLoader = createEntityLoader( LockMode.READ );
4124-
loaders.put( LockMode.READ, readLoader );
4125+
noneLockLoader = createEntityLoader( LockMode.NONE );
4126+
readLockLoader = createEntityLoader( LockMode.READ );
41254127

4126-
//TODO: inexact, what we really need to know is: are any outer joins used?
4127-
boolean disableForUpdate = getSubclassTableSpan() > 1 &&
4128-
hasSubclasses() &&
4129-
!getFactory().getDialect().supportsOuterJoinForUpdate();
4128+
final Map loaders = getLoaders();
41304129

4131-
loaders.put(
4132-
LockMode.UPGRADE,
4133-
disableForUpdate ?
4134-
readLoader :
4135-
createEntityLoader( LockMode.UPGRADE )
4136-
);
4137-
loaders.put(
4138-
LockMode.UPGRADE_NOWAIT,
4139-
disableForUpdate ?
4140-
readLoader :
4141-
createEntityLoader( LockMode.UPGRADE_NOWAIT )
4142-
);
4143-
loaders.put(
4144-
LockMode.UPGRADE_SKIPLOCKED,
4145-
disableForUpdate ?
4146-
readLoader :
4147-
createEntityLoader( LockMode.UPGRADE_SKIPLOCKED )
4148-
);
4149-
loaders.put(
4150-
LockMode.FORCE,
4151-
disableForUpdate ?
4152-
readLoader :
4153-
createEntityLoader( LockMode.FORCE )
4154-
);
4155-
loaders.put(
4156-
LockMode.PESSIMISTIC_READ,
4157-
disableForUpdate ?
4158-
readLoader :
4159-
createEntityLoader( LockMode.PESSIMISTIC_READ )
4160-
);
4161-
loaders.put(
4162-
LockMode.PESSIMISTIC_WRITE,
4163-
disableForUpdate ?
4164-
readLoader :
4165-
createEntityLoader( LockMode.PESSIMISTIC_WRITE )
4166-
);
4167-
loaders.put(
4168-
LockMode.PESSIMISTIC_FORCE_INCREMENT,
4169-
disableForUpdate ?
4170-
readLoader :
4171-
createEntityLoader( LockMode.PESSIMISTIC_FORCE_INCREMENT )
4172-
);
4173-
loaders.put( LockMode.OPTIMISTIC, createEntityLoader( LockMode.OPTIMISTIC ) );
4174-
loaders.put( LockMode.OPTIMISTIC_FORCE_INCREMENT, createEntityLoader( LockMode.OPTIMISTIC_FORCE_INCREMENT ) );
4130+
// The loaders for the other lock modes are lazily loaded and will later be stored in this map.
41754131

41764132
loaders.put(
41774133
"merge",
@@ -4183,6 +4139,46 @@ protected void createLoaders() {
41834139
);
41844140
}
41854141

4142+
private UniqueEntityLoader getLoaderByLockMode(LockMode lockMode) {
4143+
if ( LockMode.NONE == lockMode ) {
4144+
return noneLockLoader;
4145+
}
4146+
else if ( LockMode.READ == lockMode ) {
4147+
return readLockLoader;
4148+
}
4149+
4150+
return loaders.computeIfAbsent( lockMode, this::createLazyLoadedEntityLoader );
4151+
}
4152+
4153+
private UniqueEntityLoader createLazyLoadedEntityLoader(Object lockModeObject) {
4154+
// Unfortunately, the loaders map mixes LockModes and Strings as keys so we need to accept an Object.
4155+
// The cast is safe as we will always call this method with a LockMode.
4156+
LockMode lockMode = (LockMode) lockModeObject;
4157+
4158+
switch ( lockMode ) {
4159+
case NONE:
4160+
case READ:
4161+
case OPTIMISTIC:
4162+
case OPTIMISTIC_FORCE_INCREMENT:
4163+
return createEntityLoader( lockMode );
4164+
case UPGRADE:
4165+
case UPGRADE_NOWAIT:
4166+
case UPGRADE_SKIPLOCKED:
4167+
case FORCE:
4168+
case PESSIMISTIC_READ:
4169+
case PESSIMISTIC_WRITE:
4170+
case PESSIMISTIC_FORCE_INCREMENT:
4171+
//TODO: inexact, what we really need to know is: are any outer joins used?
4172+
boolean disableForUpdate = getSubclassTableSpan() > 1 &&
4173+
hasSubclasses() &&
4174+
!getFactory().getDialect().supportsOuterJoinForUpdate();
4175+
4176+
return disableForUpdate ? readLockLoader : createEntityLoader( lockMode );
4177+
default:
4178+
throw new IllegalStateException( String.format( "Lock mode %1$s not supported by entity loaders.", lockMode ) );
4179+
}
4180+
}
4181+
41864182
protected void createQueryLoader() {
41874183
if ( loaderName != null ) {
41884184
queryLoader = new NamedQueryLoader( loaderName, this );
@@ -4276,7 +4272,7 @@ else if ( lockOptions.getTimeOut() != LockOptions.WAIT_FOREVER ) {
42764272
return createEntityLoader( lockOptions, session.getLoadQueryInfluencers() );
42774273
}
42784274
else {
4279-
return (UniqueEntityLoader) getLoaders().get( lockOptions.getLockMode() );
4275+
return (UniqueEntityLoader) getLoaderByLockMode( lockOptions.getLockMode() );
42804276
}
42814277
}
42824278

0 commit comments

Comments
 (0)