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;
/**
* Base support for MultiIdEntityLoader implementations
* Base support for {@link MultiIdEntityLoader} implementations.
*
* @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 SessionFactoryImplementor sessionFactory;
private EntityIdentifierMapping identifierMapping;
private final EntityIdentifierMapping identifierMapping;
public AbstractMultiIdEntityLoader(EntityMappingType entityDescriptor, SessionFactoryImplementor sessionFactory) {
this.entityDescriptor = entityDescriptor;
this.sessionFactory = sessionFactory;
}
@Override
public void prepare() {
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;
/**
* 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
* entire batch of ids.
*
@ -40,14 +40,14 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
*/
public class EntityBatchLoaderArrayParam<T>
extends SingleIdEntityLoaderSupport<T>
implements EntityBatchLoader<T>, SqlArrayMultiKeyLoader, Preparable {
implements EntityBatchLoader<T>, SqlArrayMultiKeyLoader {
private final int domainBatchSize;
private BasicEntityIdentifierMapping identifierMapping;
private JdbcMapping arrayJdbcMapping;
private JdbcParameter jdbcParameter;
private SelectStatement sqlAst;
private JdbcOperationQuerySelect jdbcSelectOperation;
private final BasicEntityIdentifierMapping identifierMapping;
private final JdbcMapping arrayJdbcMapping;
private final JdbcParameter jdbcParameter;
private final SelectStatement sqlAst;
private final JdbcOperationQuerySelect jdbcSelectOperation;
/**
@ -75,7 +75,32 @@ public class EntityBatchLoaderArrayParam<T>
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
public int getDomainBatchSize() {
@ -151,35 +176,6 @@ public class EntityBatchLoaderArrayParam<T>
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
public String toString() {
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;
/**
* An EntityBatchLoader using one or more SQL queries, which each initialize up to
* {@linkplain #getSqlBatchSize()} entities using a SQL IN predicate restriction -
* An {@link EntityBatchLoader} using one or more SQL queries, which each initialize up
* to {@linkplain #getSqlBatchSize()} entities using a SQL IN predicate restriction -
* e.g., {@code ... where id in (?,?,...)}.
* <p/>
* <p>
* 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}.
*
@ -46,13 +46,13 @@ import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LO
*/
public class EntityBatchLoaderInPredicate<T>
extends SingleIdEntityLoaderSupport<T>
implements EntityBatchLoader<T>, SqlInPredicateMultiKeyLoader, Preparable {
implements EntityBatchLoader<T>, SqlInPredicateMultiKeyLoader {
private final int domainBatchSize;
private final int sqlBatchSize;
private List<JdbcParameter> jdbcParameters;
private SelectStatement sqlAst;
private JdbcOperationQuerySelect jdbcSelectOperation;
private final List<JdbcParameter> jdbcParameters;
private final SelectStatement sqlAst;
private final JdbcOperationQuerySelect jdbcSelectOperation;
/**
* @param domainBatchSize The maximum number of entities we will initialize for each {@link #load load}
@ -77,6 +77,31 @@ public class EntityBatchLoaderInPredicate<T>
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
@ -300,34 +325,6 @@ public class EntityBatchLoaderInPredicate<T>
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
public String toString() {
return String.format(

View File

@ -48,12 +48,20 @@ import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
/**
* @author Steve Ebersole
*/
public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader, Preparable {
private JdbcMapping arrayJdbcMapping;
private JdbcParameter jdbcParameter;
public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader {
private final JdbcMapping arrayJdbcMapping;
private final JdbcParameter jdbcParameter;
public MultiIdEntityLoaderArrayParam(EntityMappingType entityDescriptor, SessionFactoryImplementor 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
@ -387,17 +395,4 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
//noinspection unchecked
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;
/**
* Standard implementation of SingleIdEntityLoader
* Standard implementation of {@link org.hibernate.loader.ast.spi.SingleIdEntityLoader}.
*
* @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<CascadingFetchProfile, SingleIdLoadPlan> selectByInternalCascadeProfile;
@ -43,10 +43,6 @@ public class SingleIdEntityLoaderStandardImpl<T> extends SingleIdEntityLoaderSup
SessionFactoryImplementor sessionFactory) {
// todo (6.0) : consider creating a base AST and "cloning" it
super( entityDescriptor, sessionFactory );
}
@Override
public void prepare() {
// see `org.hibernate.persister.entity.AbstractEntityPersister#createLoaders`
// we should pre-load a few - maybe LockMode.NONE and LockMode.READ
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.jdbc.mutation.spi.MutationExecutorService;
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.CascadeStyle;
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.jdbc.Expectation;
import org.hibernate.jdbc.TooManyRowsAffectedException;
import org.hibernate.loader.ast.internal.MultiKeyLoadHelper;
import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper;
import org.hibernate.engine.profile.internal.FetchProfileAffectee;
import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
import org.hibernate.loader.ast.internal.LoaderSqlAstCreationState;
import org.hibernate.loader.ast.internal.MultiIdEntityLoaderArrayParam;
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.SingleIdEntityLoaderProvidedQueryImpl;
import org.hibernate.loader.ast.internal.SingleIdEntityLoaderStandardImpl;
import org.hibernate.loader.ast.internal.SingleUniqueKeyEntityLoaderStandard;
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.MultiIdLoadOptions;
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
final NamedQueryMemento memento = getNamedQueryMemento( null );
singleIdLoader = new SingleIdEntityLoaderProvidedQueryImpl<>( this, memento );
prepareLoader( singleIdLoader );
}
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},
* depending upon the value of the {@code lock} parameter
@ -3463,7 +3441,7 @@ public abstract class AbstractEntityPersister
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
// no subselect fetching for entities for now
return isAffectedByInfluencers( influencers )
? createAndPrepareSingleIdEntityLoader( influencers )
? createSingleIdEntityLoader( influencers )
: getSingleIdLoader();
}
}