HHH-16651 get rid of Preparable interface

I can't figure out why it's required but perhaps I'm missing something
This commit is contained in:
Gavin 2023-05-21 22:23:23 +02:00 committed by Gavin King
parent bbd8df93ca
commit c2ceb4c279
7 changed files with 84 additions and 149 deletions

View File

@ -16,23 +16,18 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import java.util.List; import java.util.List;
/** /**
* Base support for MultiIdEntityLoader implementations * Base support for {@link MultiIdEntityLoader} implementations.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoader<T>, Preparable { public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoader<T> {
private final EntityMappingType entityDescriptor; private final EntityMappingType entityDescriptor;
private final SessionFactoryImplementor sessionFactory; private final SessionFactoryImplementor sessionFactory;
private final EntityIdentifierMapping identifierMapping;
private EntityIdentifierMapping identifierMapping;
public AbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { public AbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) {
this.entityDescriptor = entityDescriptor; this.entityDescriptor = entityDescriptor;
this.sessionFactory = sessionFactory; this.sessionFactory = sessionFactory;
}
@Override
public void prepare() {
identifierMapping = getLoadable().getIdentifierMapping(); identifierMapping = getLoadable().getIdentifierMapping();
} }

View File

@ -32,7 +32,7 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
/** /**
* SingleIdEntityLoaderSupport implementation based on using a single * {@link SingleIdEntityLoaderSupport} implementation based on using a single
* {@linkplain org.hibernate.type.SqlTypes#ARRAY array} parameter to pass the * {@linkplain org.hibernate.type.SqlTypes#ARRAY array} parameter to pass the
* entire batch of ids. * entire batch of ids.
* *
@ -40,14 +40,14 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
*/ */
public class EntityBatchLoaderArrayParam<T> public class EntityBatchLoaderArrayParam<T>
extends SingleIdEntityLoaderSupport<T> extends SingleIdEntityLoaderSupport<T>
implements EntityBatchLoader<T>, SqlArrayMultiKeyLoader, Preparable { implements EntityBatchLoader<T>, SqlArrayMultiKeyLoader {
private final int domainBatchSize; private final int domainBatchSize;
private BasicEntityIdentifierMapping identifierMapping; private final BasicEntityIdentifierMapping identifierMapping;
private JdbcMapping arrayJdbcMapping; private final JdbcMapping arrayJdbcMapping;
private JdbcParameter jdbcParameter; private final JdbcParameter jdbcParameter;
private SelectStatement sqlAst; private final SelectStatement sqlAst;
private JdbcOperationQuerySelect jdbcSelectOperation; private final JdbcOperationQuerySelect jdbcSelectOperation;
/** /**
@ -75,7 +75,32 @@ public class EntityBatchLoaderArrayParam<T>
domainBatchSize domainBatchSize
); );
} }
}
identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping();
final Class<?> arrayClass =
Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass();
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
identifierMapping.getJdbcMapping(),
arrayClass,
sessionFactory
);
jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping );
sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter(
getLoadable(),
identifierMapping,
new LoadQueryInfluencers( sessionFactory ),
LockOptions.NONE,
jdbcParameter,
sessionFactory
);
jdbcSelectOperation = sessionFactory.getJdbcServices()
.getJdbcEnvironment()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( sessionFactory, sqlAst )
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE ); }
@Override @Override
public int getDomainBatchSize() { public int getDomainBatchSize() {
@ -151,35 +176,6 @@ public class EntityBatchLoaderArrayParam<T>
return load( pkValue, null, lockOptions, readOnly, session ); return load( pkValue, null, lockOptions, readOnly, session );
} }
@Override
public void prepare() {
identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping();
final Class<?> arrayClass =
Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass();
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
identifierMapping.getJdbcMapping(),
arrayClass,
sessionFactory
);
jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping );
sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter(
getLoadable(),
identifierMapping,
new LoadQueryInfluencers( sessionFactory ),
LockOptions.NONE,
jdbcParameter,
sessionFactory
);
jdbcSelectOperation = sessionFactory.getJdbcServices()
.getJdbcEnvironment()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( sessionFactory, sqlAst )
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
}
@Override @Override
public String toString() { public String toString() {
return String.format( return String.format(

View File

@ -35,10 +35,10 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
/** /**
* An EntityBatchLoader using one or more SQL queries, which each initialize up to * An {@link EntityBatchLoader} using one or more SQL queries, which each initialize up
* {@linkplain #getSqlBatchSize()} entities using a SQL IN predicate restriction - * to {@linkplain #getSqlBatchSize()} entities using a SQL IN predicate restriction -
* e.g., {@code ... where id in (?,?,...)}. * e.g., {@code ... where id in (?,?,...)}.
* <p/> * <p>
* The number of parameters rendered into the SQL is controlled by {@linkplain #getSqlBatchSize()}. * The number of parameters rendered into the SQL is controlled by {@linkplain #getSqlBatchSize()}.
* Any unused parameter slots for a particular execution are set to {@code null}. * Any unused parameter slots for a particular execution are set to {@code null}.
* *
@ -46,13 +46,13 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
*/ */
public class EntityBatchLoaderInPredicate<T> public class EntityBatchLoaderInPredicate<T>
extends SingleIdEntityLoaderSupport<T> extends SingleIdEntityLoaderSupport<T>
implements EntityBatchLoader<T>, SqlInPredicateMultiKeyLoader, Preparable { implements EntityBatchLoader<T>, SqlInPredicateMultiKeyLoader {
private final int domainBatchSize; private final int domainBatchSize;
private final int sqlBatchSize; private final int sqlBatchSize;
private List<JdbcParameter> jdbcParameters; private final List<JdbcParameter> jdbcParameters;
private SelectStatement sqlAst; private final SelectStatement sqlAst;
private JdbcOperationQuerySelect jdbcSelectOperation; private final JdbcOperationQuerySelect jdbcSelectOperation;
/** /**
* @param domainBatchSize The maximum number of entities we will initialize for each {@link #load load} * @param domainBatchSize The maximum number of entities we will initialize for each {@link #load load}
@ -77,6 +77,31 @@ public class EntityBatchLoaderInPredicate<T>
sqlBatchSize sqlBatchSize
); );
} }
EntityIdentifierMapping identifierMapping = getLoadable().getIdentifierMapping();
final int expectedNumberOfParameters = identifierMapping.getJdbcTypeCount() * sqlBatchSize;
jdbcParameters = arrayList( expectedNumberOfParameters );
sqlAst = LoaderSelectBuilder.createSelect(
getLoadable(),
// null here means to select everything
null,
identifierMapping,
null,
sqlBatchSize,
new LoadQueryInfluencers( sessionFactory ),
LockOptions.NONE,
jdbcParameters::add,
sessionFactory
);
assert jdbcParameters.size() == expectedNumberOfParameters;
jdbcSelectOperation = sessionFactory.getJdbcServices()
.getJdbcEnvironment()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( sessionFactory, sqlAst )
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
} }
@Override @Override
@ -300,34 +325,6 @@ public class EntityBatchLoaderInPredicate<T>
entityKeys.forEach( batchFetchQueue::removeBatchLoadableEntityKey ); entityKeys.forEach( batchFetchQueue::removeBatchLoadableEntityKey );
} }
@Override
public void prepare() {
EntityIdentifierMapping identifierMapping = getLoadable().getIdentifierMapping();
final int expectedNumberOfParameters = identifierMapping.getJdbcTypeCount() * sqlBatchSize;
jdbcParameters = arrayList( expectedNumberOfParameters );
sqlAst = LoaderSelectBuilder.createSelect(
getLoadable(),
// null here means to select everything
null,
identifierMapping,
null,
sqlBatchSize,
new LoadQueryInfluencers( sessionFactory ),
LockOptions.NONE,
jdbcParameters::add,
sessionFactory
);
assert jdbcParameters.size() == expectedNumberOfParameters;
jdbcSelectOperation = sessionFactory.getJdbcServices()
.getJdbcEnvironment()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( sessionFactory, sqlAst )
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
}
@Override @Override
public String toString() { public String toString() {
return String.format( return String.format(

View File

@ -48,12 +48,20 @@ import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader, Preparable { public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader {
private JdbcMapping arrayJdbcMapping; private final JdbcMapping arrayJdbcMapping;
private JdbcParameter jdbcParameter; private final JdbcParameter jdbcParameter;
public MultiIdEntityLoaderArrayParam(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) { public MultiIdEntityLoaderArrayParam(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) {
super( entityDescriptor, sessionFactory ); super( entityDescriptor, sessionFactory );
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
getIdentifierMapping().getJdbcMapping(),
arrayClass,
getSessionFactory()
);
jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping );
} }
@Override @Override
@ -387,17 +395,4 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
//noinspection unchecked //noinspection unchecked
return (X[]) Array.newInstance( getIdentifierMapping().getJavaType().getJavaTypeClass(), length ); return (X[]) Array.newInstance( getIdentifierMapping().getJavaType().getJavaTypeClass(), length );
} }
@Override
public void prepare() {
super.prepare();
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
getIdentifierMapping().getJdbcMapping(),
arrayClass,
getSessionFactory()
);
jdbcParameter = new JdbcParameterImpl( arrayJdbcMapping );
}
} }

View File

@ -1,22 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.loader.ast.internal;
/**
* Contract for Loader instances wishing to have a "finish initialization" callback after its Loadable
* has finished initializing.
*
* This allows the owner to create the Loader during its construction and trigger its "prepare" later
*
* @author Steve Ebersole
*/
public interface Preparable {
/**
* Perform the preparation
*/
void prepare();
}

View File

@ -24,11 +24,11 @@ import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
/** /**
* Standard implementation of SingleIdEntityLoader * Standard implementation of {@link org.hibernate.loader.ast.spi.SingleIdEntityLoader}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SingleIdEntityLoaderStandardImpl<T> extends SingleIdEntityLoaderSupport<T> implements Preparable { public class SingleIdEntityLoaderStandardImpl<T> extends SingleIdEntityLoaderSupport<T> {
private EnumMap<LockMode, SingleIdLoadPlan> selectByLockMode = new EnumMap<>( LockMode.class ); private EnumMap<LockMode, SingleIdLoadPlan> selectByLockMode = new EnumMap<>( LockMode.class );
private EnumMap<CascadingFetchProfile, SingleIdLoadPlan> selectByInternalCascadeProfile; private EnumMap<CascadingFetchProfile, SingleIdLoadPlan> selectByInternalCascadeProfile;
@ -43,10 +43,6 @@ public class SingleIdEntityLoaderStandardImpl<T> extends SingleIdEntityLoaderSup
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
// todo (6.0) : consider creating a base AST and "cloning" it // todo (6.0) : consider creating a base AST and "cloning" it
super( entityDescriptor, sessionFactory ); super( entityDescriptor, sessionFactory );
}
@Override
public void prepare() {
// see `org.hibernate.persister.entity.AbstractEntityPersister#createLoaders` // see `org.hibernate.persister.entity.AbstractEntityPersister#createLoaders`
// we should pre-load a few - maybe LockMode.NONE and LockMode.READ // we should pre-load a few - maybe LockMode.NONE and LockMode.READ
final LockOptions lockOptions = LockOptions.NONE; final LockOptions lockOptions = LockOptions.NONE;

View File

@ -76,7 +76,6 @@ import org.hibernate.engine.internal.MutableEntityEntryFactory;
import org.hibernate.engine.internal.StatefulPersistenceContext; import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService; import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.CachedNaturalIdValueSource; import org.hibernate.engine.spi.CachedNaturalIdValueSource;
import org.hibernate.engine.spi.CascadeStyle; import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CollectionKey; import org.hibernate.engine.spi.CollectionKey;
@ -118,20 +117,17 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.LockModeEnumMap; import org.hibernate.internal.util.collections.LockModeEnumMap;
import org.hibernate.jdbc.Expectation; import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.TooManyRowsAffectedException; import org.hibernate.jdbc.TooManyRowsAffectedException;
import org.hibernate.loader.ast.internal.MultiKeyLoadHelper;
import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper; import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper;
import org.hibernate.engine.profile.internal.FetchProfileAffectee; import org.hibernate.engine.profile.internal.FetchProfileAffectee;
import org.hibernate.loader.ast.internal.LoaderSelectBuilder; import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
import org.hibernate.loader.ast.internal.LoaderSqlAstCreationState; import org.hibernate.loader.ast.internal.LoaderSqlAstCreationState;
import org.hibernate.loader.ast.internal.MultiIdEntityLoaderArrayParam; import org.hibernate.loader.ast.internal.MultiIdEntityLoaderArrayParam;
import org.hibernate.loader.ast.internal.MultiIdEntityLoaderStandard; import org.hibernate.loader.ast.internal.MultiIdEntityLoaderStandard;
import org.hibernate.loader.ast.internal.Preparable;
import org.hibernate.loader.ast.internal.SingleIdArrayLoadPlan; import org.hibernate.loader.ast.internal.SingleIdArrayLoadPlan;
import org.hibernate.loader.ast.internal.SingleIdEntityLoaderProvidedQueryImpl; import org.hibernate.loader.ast.internal.SingleIdEntityLoaderProvidedQueryImpl;
import org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl; import org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl;
import org.hibernate.loader.ast.internal.SingleUniqueKeyEntityLoaderStandard; import org.hibernate.loader.ast.internal.SingleUniqueKeyEntityLoaderStandard;
import org.hibernate.loader.ast.spi.BatchLoaderFactory; import org.hibernate.loader.ast.spi.BatchLoaderFactory;
import org.hibernate.loader.ast.spi.Loader;
import org.hibernate.loader.ast.spi.MultiIdEntityLoader; import org.hibernate.loader.ast.spi.MultiIdEntityLoader;
import org.hibernate.loader.ast.spi.MultiIdLoadOptions; import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
@ -3393,31 +3389,13 @@ public abstract class AbstractEntityPersister
// We must resolve the named query on-demand through the boot model because it isn't initialized yet // We must resolve the named query on-demand through the boot model because it isn't initialized yet
final NamedQueryMemento memento = getNamedQueryMemento( null ); final NamedQueryMemento memento = getNamedQueryMemento( null );
singleIdLoader = new SingleIdEntityLoaderProvidedQueryImpl<>( this, memento ); singleIdLoader = new SingleIdEntityLoaderProvidedQueryImpl<>( this, memento );
prepareLoader( singleIdLoader );
} }
else { else {
singleIdLoader = createAndPrepareSingleIdEntityLoader( new LoadQueryInfluencers( factory ) ); singleIdLoader = createSingleIdEntityLoader( new LoadQueryInfluencers( factory ) );
} }
multiIdLoader = buildAndPrepareMultiIdLoader(); multiIdLoader = buildMultiIdLoader();
} }
private MultiIdEntityLoader<Object> buildAndPrepareMultiIdLoader() {
MultiIdEntityLoader<Object> multiIdLoader = buildMultiIdLoader();
prepareLoader( multiIdLoader );
return multiIdLoader;
}
private SingleIdEntityLoader<?> createAndPrepareSingleIdEntityLoader(LoadQueryInfluencers influencers) {
SingleIdEntityLoader<?> singleIdLoader = createSingleIdEntityLoader( influencers );
prepareLoader( singleIdLoader );
return singleIdLoader;
}
private void prepareLoader(Loader loader) {
if ( loader instanceof Preparable ) {
( (Preparable) loader ).prepare();
}
}
/** /**
* Load an instance using either the {@code forUpdateLoader} or the outer joining {@code loader}, * Load an instance using either the {@code forUpdateLoader} or the outer joining {@code loader},
* depending upon the value of the {@code lock} parameter * depending upon the value of the {@code lock} parameter
@ -3463,7 +3441,7 @@ public abstract class AbstractEntityPersister
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers(); final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
// no subselect fetching for entities for now // no subselect fetching for entities for now
return isAffectedByInfluencers( influencers ) return isAffectedByInfluencers( influencers )
? createAndPrepareSingleIdEntityLoader( influencers ) ? createSingleIdEntityLoader( influencers )
: getSingleIdLoader(); : getSingleIdLoader();
} }
} }