HHH-12556 Share data structures between similar LoadPlan based EntityLoaders

This commit is contained in:
Guillaume Smet 2018-05-09 12:14:13 +02:00
parent 1c1cd47c08
commit 3834c4d149
6 changed files with 147 additions and 31 deletions

View File

@ -28,6 +28,7 @@ import org.hibernate.loader.plan.build.spi.LoadPlanBuildingAssociationVisitation
import org.hibernate.loader.plan.build.spi.MetamodelDrivenLoadPlanBuilder; import org.hibernate.loader.plan.build.spi.MetamodelDrivenLoadPlanBuilder;
import org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader; import org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader;
import org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory; import org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory;
import org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails;
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters; import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
import org.hibernate.loader.plan.exec.spi.LoadQueryDetails; import org.hibernate.loader.plan.exec.spi.LoadQueryDetails;
import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.loader.plan.spi.LoadPlan;
@ -87,6 +88,23 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
); );
} }
protected AbstractLoadPlanBasedEntityLoader(
OuterJoinLoadable entityPersister,
SessionFactoryImplementor factory,
EntityLoadQueryDetails entityLoaderQueryDetailsTemplate,
Type uniqueKeyType,
QueryBuildingParameters buildingParameters) {
super( factory );
this.entityPersister = entityPersister;
this.uniqueKeyType = uniqueKeyType;
this.entityName = entityPersister.getEntityName();
this.staticLoadQuery = BatchingLoadQueryDetailsFactory.INSTANCE.makeEntityLoadQueryDetails(
entityLoaderQueryDetailsTemplate,
buildingParameters
);
}
@Override @Override
protected LoadQueryDetails getStaticLoadQuery() { protected LoadQueryDetails getStaticLoadQuery() {
return staticLoadQuery; return staticLoadQuery;

View File

@ -12,11 +12,11 @@ import org.hibernate.MappingException;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails;
import org.hibernate.loader.plan.exec.query.internal.QueryBuildingParametersImpl; import org.hibernate.loader.plan.exec.query.internal.QueryBuildingParametersImpl;
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters; import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
/** /**
@ -44,6 +44,7 @@ public class EntityLoader extends AbstractLoadPlanBasedEntityLoader {
public static class Builder { public static class Builder {
private final OuterJoinLoadable persister; private final OuterJoinLoadable persister;
private EntityLoader entityLoaderTemplate;
private int batchSize = 1; private int batchSize = 1;
private LoadQueryInfluencers influencers = LoadQueryInfluencers.NONE; private LoadQueryInfluencers influencers = LoadQueryInfluencers.NONE;
private LockMode lockMode = LockMode.NONE; private LockMode lockMode = LockMode.NONE;
@ -53,6 +54,11 @@ public class EntityLoader extends AbstractLoadPlanBasedEntityLoader {
this.persister = persister; this.persister = persister;
} }
public Builder withEntityLoaderTemplate(EntityLoader entityLoaderTemplate) {
this.entityLoaderTemplate = entityLoaderTemplate;
return this;
}
public Builder withBatchSize(int batchSize) { public Builder withBatchSize(int batchSize) {
this.batchSize = batchSize; this.batchSize = batchSize;
return this; return this;
@ -79,6 +85,7 @@ public class EntityLoader extends AbstractLoadPlanBasedEntityLoader {
public EntityLoader byUniqueKey(String[] keyColumnNames, Type keyType) { public EntityLoader byUniqueKey(String[] keyColumnNames, Type keyType) {
// capture current values in a new instance of QueryBuildingParametersImpl // capture current values in a new instance of QueryBuildingParametersImpl
if ( entityLoaderTemplate == null ) {
return new EntityLoader( return new EntityLoader(
persister.getFactory(), persister.getFactory(),
persister, persister,
@ -92,6 +99,21 @@ public class EntityLoader extends AbstractLoadPlanBasedEntityLoader {
) )
); );
} }
else {
return new EntityLoader(
persister.getFactory(),
persister,
entityLoaderTemplate,
keyType,
new QueryBuildingParametersImpl(
influencers,
batchSize,
lockMode,
lockOptions
)
);
}
}
} }
private EntityLoader( private EntityLoader(
@ -121,4 +143,37 @@ public class EntityLoader extends AbstractLoadPlanBasedEntityLoader {
} }
} }
} }
private EntityLoader(
SessionFactoryImplementor factory,
OuterJoinLoadable persister,
EntityLoader entityLoaderTemplate,
Type uniqueKeyType,
QueryBuildingParameters buildingParameters) throws MappingException {
super( persister, factory, entityLoaderTemplate.getStaticLoadQuery(), uniqueKeyType, buildingParameters );
if ( log.isDebugEnabled() ) {
if ( buildingParameters.getLockOptions() != null ) {
log.debugf(
"Static select for entity %s [%s:%s]: %s",
getEntityName(),
buildingParameters.getLockOptions().getLockMode(),
buildingParameters.getLockOptions().getTimeOut(),
getStaticLoadQuery().getSqlStatement()
);
}
else if ( buildingParameters.getLockMode() != null ) {
log.debugf(
"Static select for entity %s [%s]: %s",
getEntityName(),
buildingParameters.getLockMode(),
getStaticLoadQuery().getSqlStatement()
);
}
}
}
@Override
protected EntityLoadQueryDetails getStaticLoadQuery() {
return (EntityLoadQueryDetails) super.getStaticLoadQuery();
}
} }

View File

@ -20,7 +20,7 @@ import org.hibernate.loader.entity.UniqueEntityLoader;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
/** /**
* LoadPlan-based implementation of the the legacy batch loading strategy * LoadPlan-based implementation of the legacy batch loading strategy
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -57,15 +57,7 @@ public class LegacyBatchingEntityLoaderBuilder extends AbstractBatchingEntityLoa
LockMode lockMode, LockMode lockMode,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) { LoadQueryInfluencers loadQueryInfluencers) {
super( persister ); this( persister, maxBatchSize, lockMode, null, factory, loadQueryInfluencers );
this.batchSizes = ArrayHelper.getBatchSizes( maxBatchSize );
this.loaders = new EntityLoader[ batchSizes.length ];
final EntityLoader.Builder entityLoaderBuilder = EntityLoader.forEntity( persister )
.withInfluencers( loadQueryInfluencers )
.withLockMode( lockMode );
for ( int i = 0; i < batchSizes.length; i++ ) {
this.loaders[i] = entityLoaderBuilder.withBatchSize( batchSizes[i] ).byPrimaryKey();
}
} }
public LegacyBatchingEntityLoader( public LegacyBatchingEntityLoader(
@ -74,14 +66,29 @@ public class LegacyBatchingEntityLoaderBuilder extends AbstractBatchingEntityLoa
LockOptions lockOptions, LockOptions lockOptions,
SessionFactoryImplementor factory, SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) { LoadQueryInfluencers loadQueryInfluencers) {
this( persister, maxBatchSize, null, lockOptions, factory, loadQueryInfluencers );
}
protected LegacyBatchingEntityLoader(
OuterJoinLoadable persister,
int maxBatchSize,
LockMode lockMode,
LockOptions lockOptions,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) {
super( persister ); super( persister );
this.batchSizes = ArrayHelper.getBatchSizes( maxBatchSize ); this.batchSizes = ArrayHelper.getBatchSizes( maxBatchSize );
this.loaders = new EntityLoader[ batchSizes.length ]; this.loaders = new EntityLoader[ batchSizes.length ];
final EntityLoader.Builder entityLoaderBuilder = EntityLoader.forEntity( persister ) final EntityLoader.Builder entityLoaderBuilder = EntityLoader.forEntity( persister )
.withInfluencers( loadQueryInfluencers ) .withInfluencers( loadQueryInfluencers )
.withLockMode( lockMode )
.withLockOptions( lockOptions ); .withLockOptions( lockOptions );
for ( int i = 0; i < batchSizes.length; i++ ) {
this.loaders[i] = entityLoaderBuilder.withBatchSize( batchSizes[i] ).byPrimaryKey(); // we create a first entity loader to use it as a template for the others
this.loaders[0] = entityLoaderBuilder.withBatchSize( batchSizes[0] ).byPrimaryKey();
for ( int i = 1; i < batchSizes.length; i++ ) {
this.loaders[i] = entityLoaderBuilder.withEntityLoaderTemplate( this.loaders[0] ).withBatchSize( batchSizes[i] ).byPrimaryKey();
} }
} }

View File

@ -90,6 +90,15 @@ public abstract class AbstractLoadQueryDetails implements LoadQueryDetails {
protected final SessionFactoryImplementor getSessionFactory() { protected final SessionFactoryImplementor getSessionFactory() {
return queryProcessor.getSessionFactory(); return queryProcessor.getSessionFactory();
} }
protected LoadPlan getLoadPlan() {
return loadPlan;
}
protected String[] getKeyColumnNames() {
return keyColumnNames;
}
/** /**
* Main entry point for properly handling the FROM clause and and joins and restrictions * Main entry point for properly handling the FROM clause and and joins and restrictions
* *

View File

@ -68,6 +68,23 @@ public class BatchingLoadQueryDetailsFactory {
); );
} }
/**
* Returns a EntityLoadQueryDetails object based on an existing one and additional elements specific to this one.
*
* @param entityLoadQueryDetailsTemplate the template
* @param buildingParameters And influencers that would affect the generated SQL (mostly we are concerned with those
* that add additional joins here)
* @return The EntityLoadQueryDetails
*/
public LoadQueryDetails makeEntityLoadQueryDetails(
EntityLoadQueryDetails entityLoadQueryDetailsTemplate,
QueryBuildingParameters buildingParameters) {
return new EntityLoadQueryDetails(
entityLoadQueryDetailsTemplate,
buildingParameters
);
}
/** /**
* Constructs a BasicCollectionLoadQueryDetails object from the given inputs. * Constructs a BasicCollectionLoadQueryDetails object from the given inputs.
* *

View File

@ -10,8 +10,6 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import org.hibernate.LockOptions;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -20,7 +18,6 @@ import org.hibernate.loader.plan.exec.process.internal.AbstractRowReader;
import org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl; import org.hibernate.loader.plan.exec.process.internal.EntityReferenceInitializerImpl;
import org.hibernate.loader.plan.exec.process.internal.EntityReturnReader; import org.hibernate.loader.plan.exec.process.internal.EntityReturnReader;
import org.hibernate.loader.plan.exec.process.internal.ResultSetProcessingContextImpl; import org.hibernate.loader.plan.exec.process.internal.ResultSetProcessingContextImpl;
import org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorHelper;
import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer; import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer;
import org.hibernate.loader.plan.exec.process.spi.ReaderCollector; import org.hibernate.loader.plan.exec.process.spi.ReaderCollector;
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessingContext; import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessingContext;
@ -31,12 +28,9 @@ import org.hibernate.loader.plan.exec.spi.EntityReferenceAliases;
import org.hibernate.loader.plan.spi.EntityReturn; import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.LoadPlan; import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.QuerySpace; import org.hibernate.loader.plan.spi.QuerySpace;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.OuterJoinLoadable; import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.entity.Queryable; import org.hibernate.persister.entity.Queryable;
import org.hibernate.type.CompositeType;
import org.hibernate.type.Type;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -90,6 +84,22 @@ public class EntityLoadQueryDetails extends AbstractLoadQueryDetails {
generate(); generate();
} }
protected EntityLoadQueryDetails(
EntityLoadQueryDetails initialEntityLoadQueryDetails,
QueryBuildingParameters buildingParameters) {
super(
initialEntityLoadQueryDetails.getLoadPlan(),
(AliasResolutionContextImpl) initialEntityLoadQueryDetails.getAliasResolutionContext(),
buildingParameters,
initialEntityLoadQueryDetails.getKeyColumnNames(),
initialEntityLoadQueryDetails.getRootReturn(),
initialEntityLoadQueryDetails.getSessionFactory()
);
this.entityReferenceAliases = initialEntityLoadQueryDetails.entityReferenceAliases;
this.readerCollector = initialEntityLoadQueryDetails.readerCollector;
generate();
}
private EntityReturn getRootEntityReturn() { private EntityReturn getRootEntityReturn() {
return (EntityReturn) getRootReturn(); return (EntityReturn) getRootReturn();
} }