further cleanups on multi id loaders
Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
6c5f577223
commit
10c83d8370
|
@ -6,22 +6,27 @@ package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
import org.hibernate.event.spi.LoadEvent;
|
import org.hibernate.event.spi.LoadEvent;
|
||||||
import org.hibernate.event.spi.LoadEventListener;
|
import org.hibernate.event.spi.LoadEventListener;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
|
||||||
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.metamodel.mapping.EntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||||
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderHelper.getReadOnlyFromLoadQueryInfluencers;
|
||||||
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base support for {@link MultiIdEntityLoader} implementations.
|
* Base support for {@link MultiIdEntityLoader} implementations.
|
||||||
|
@ -51,6 +56,18 @@ public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoa
|
||||||
return identifierMapping;
|
return identifierMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected JdbcServices getJdbcServices() {
|
||||||
|
return getSessionFactory().getJdbcServices();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
|
||||||
|
return getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JdbcSelectExecutor getJdbcSelectExecutor() {
|
||||||
|
return getJdbcServices().getJdbcSelectExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityMappingType getLoadable() {
|
public EntityMappingType getLoadable() {
|
||||||
return getEntityDescriptor();
|
return getEntityDescriptor();
|
||||||
|
@ -71,9 +88,8 @@ public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoa
|
||||||
Object[] ids,
|
Object[] ids,
|
||||||
MultiIdLoadOptions loadOptions,
|
MultiIdLoadOptions loadOptions,
|
||||||
EventSource session) {
|
EventSource session) {
|
||||||
if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) {
|
if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) {
|
||||||
MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.tracef( "#performOrderedMultiLoad(`%s`, ..)",
|
MULTI_KEY_LOAD_LOGGER.tracef( "#performOrderedMultiLoad(`%s`, ..)", getLoadable().getEntityName() );
|
||||||
getLoadable().getEntityName() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert loadOptions.isOrderReturnEnabled();
|
assert loadOptions.isOrderReturnEnabled();
|
||||||
|
@ -87,7 +103,7 @@ public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoa
|
||||||
|
|
||||||
final int maxBatchSize = maxBatchSize( ids, loadOptions );
|
final int maxBatchSize = maxBatchSize( ids, loadOptions );
|
||||||
|
|
||||||
final List<Object> result = CollectionHelper.arrayList( ids.length );
|
final List<Object> result = arrayList( ids.length );
|
||||||
|
|
||||||
final List<Object> idsInBatch = new ArrayList<>();
|
final List<Object> idsInBatch = new ArrayList<>();
|
||||||
final List<Integer> elementPositionsLoadedByBatch = new ArrayList<>();
|
final List<Integer> elementPositionsLoadedByBatch = new ArrayList<>();
|
||||||
|
@ -146,7 +162,7 @@ public abstract class AbstractMultiIdEntityLoader<T> implements MultiIdEntityLoa
|
||||||
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
||||||
lockOptions,
|
lockOptions,
|
||||||
session,
|
session,
|
||||||
LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session )
|
getReadOnlyFromLoadQueryInfluencers( session )
|
||||||
);
|
);
|
||||||
|
|
||||||
Object managedEntity = null;
|
Object managedEntity = null;
|
||||||
|
|
|
@ -10,13 +10,11 @@ import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.engine.internal.BatchFetchQueueHelper;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.engine.spi.BatchFetchQueue;
|
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SubselectFetch;
|
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
import org.hibernate.event.spi.LoadEvent;
|
import org.hibernate.event.spi.LoadEvent;
|
||||||
import org.hibernate.event.spi.LoadEventListener;
|
import org.hibernate.event.spi.LoadEventListener;
|
||||||
|
@ -28,6 +26,7 @@ import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
|
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
import org.hibernate.sql.exec.internal.JdbcParameterBindingImpl;
|
||||||
|
@ -36,6 +35,7 @@ import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
||||||
|
import org.hibernate.sql.exec.spi.JdbcSelectExecutor;
|
||||||
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
||||||
import org.hibernate.sql.results.spi.ManagedResultConsumer;
|
import org.hibernate.sql.results.spi.ManagedResultConsumer;
|
||||||
|
|
||||||
|
@ -43,8 +43,15 @@ import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
|
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
|
import static org.hibernate.engine.internal.BatchFetchQueueHelper.removeBatchLoadableEntityKey;
|
||||||
|
import static org.hibernate.engine.spi.SubselectFetch.createRegistrationHandler;
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
|
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
|
||||||
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderHelper.getReadOnlyFromLoadQueryInfluencers;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderHelper.loadByArrayParameter;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderSelectBuilder.createSelectBySingleArrayParameter;
|
||||||
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.resolveArrayJdbcMapping;
|
||||||
|
import static org.hibernate.sql.exec.spi.JdbcParameterBindings.NO_BINDINGS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
|
@ -52,13 +59,13 @@ import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFrom
|
||||||
public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader {
|
public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoader<E> implements SqlArrayMultiKeyLoader {
|
||||||
private final JdbcMapping arrayJdbcMapping;
|
private final JdbcMapping arrayJdbcMapping;
|
||||||
private final JdbcParameter jdbcParameter;
|
private final JdbcParameter jdbcParameter;
|
||||||
private final int idJdbcTypeCount;
|
|
||||||
|
|
||||||
public MultiIdEntityLoaderArrayParam(EntityMappingType entityDescriptor, int identifierColumnSpan, SessionFactoryImplementor sessionFactory) {
|
public MultiIdEntityLoaderArrayParam(
|
||||||
|
EntityMappingType entityDescriptor,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
super( entityDescriptor, sessionFactory );
|
super( entityDescriptor, sessionFactory );
|
||||||
this.idJdbcTypeCount = identifierColumnSpan;
|
|
||||||
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
|
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
|
||||||
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
|
arrayJdbcMapping = resolveArrayJdbcMapping(
|
||||||
getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
|
getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
|
||||||
getIdentifierMapping().getJdbcMapping(),
|
getIdentifierMapping().getJdbcMapping(),
|
||||||
arrayClass,
|
arrayClass,
|
||||||
|
@ -83,7 +90,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
// the element value at this position in the result List should be
|
// the element value at this position in the result List should be
|
||||||
// the EntityKey for that entity - reuse it
|
// the EntityKey for that entity - reuse it
|
||||||
final EntityKey entityKey = (EntityKey) result.get( position );
|
final EntityKey entityKey = (EntityKey) result.get( position );
|
||||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( entityKey, session );
|
removeBatchLoadableEntityKey( entityKey, session );
|
||||||
Object entity = persistenceContext.getEntity( entityKey );
|
Object entity = persistenceContext.getEntity( entityKey );
|
||||||
if ( entity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() ) {
|
if ( entity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() ) {
|
||||||
// make sure it is not DELETED
|
// make sure it is not DELETED
|
||||||
|
@ -102,28 +109,20 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions) {
|
protected int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions) {
|
||||||
if ( loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0 ) {
|
final Integer explicitBatchSize = loadOptions.getBatchSize();
|
||||||
return loadOptions.getBatchSize();
|
return explicitBatchSize != null && explicitBatchSize > 0
|
||||||
}
|
? explicitBatchSize
|
||||||
else {
|
// disable batching by default
|
||||||
// disable batching by default
|
: ids.length;
|
||||||
return ids.length;
|
|
||||||
// return getSessionFactory().getJdbcServices().getJdbcEnvironment().getDialect()
|
|
||||||
// .getBatchLoadSizingStrategy().determineOptimalBatchLoadSize(
|
|
||||||
// idJdbcTypeCount,
|
|
||||||
// ids.length,
|
|
||||||
// getSessionFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled()
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadEntitiesById(
|
protected void loadEntitiesById(
|
||||||
List<Object> idsToLoadFromDatabase,
|
List<Object> idsInBatch,
|
||||||
LockOptions lockOptions,
|
LockOptions lockOptions,
|
||||||
MultiIdLoadOptions loadOptions,
|
MultiIdLoadOptions loadOptions,
|
||||||
EventSource session) {
|
EventSource session) {
|
||||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter(
|
final SelectStatement sqlAst = createSelectBySingleArrayParameter(
|
||||||
getLoadable(),
|
getLoadable(),
|
||||||
getIdentifierMapping(),
|
getIdentifierMapping(),
|
||||||
session.getLoadQueryInfluencers(),
|
session.getLoadQueryInfluencers(),
|
||||||
|
@ -131,42 +130,31 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
jdbcParameter,
|
jdbcParameter,
|
||||||
getSessionFactory()
|
getSessionFactory()
|
||||||
);
|
);
|
||||||
final JdbcOperationQuerySelect jdbcSelectOperation = getSessionFactory().getJdbcServices()
|
|
||||||
.getJdbcEnvironment()
|
|
||||||
.getSqlAstTranslatorFactory()
|
|
||||||
.buildSelectTranslator( getSessionFactory(), sqlAst )
|
|
||||||
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
|
|
||||||
|
|
||||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(1);
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(1);
|
||||||
jdbcParameterBindings.addBinding(
|
jdbcParameterBindings.addBinding( jdbcParameter,
|
||||||
jdbcParameter,
|
new JdbcParameterBindingImpl( arrayJdbcMapping, idsInBatch.toArray( createTypedArray(0) ) ) );
|
||||||
new JdbcParameterBindingImpl( arrayJdbcMapping, idsToLoadFromDatabase.toArray( createTypedArray(0 ) ) )
|
|
||||||
);
|
|
||||||
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
getJdbcSelectExecutor().executeQuery(
|
||||||
final BatchFetchQueue batchFetchQueue = persistenceContext.getBatchFetchQueue();
|
getSqlAstTranslatorFactory().buildSelectTranslator( getSessionFactory(), sqlAst )
|
||||||
|
.translate( NO_BINDINGS, QueryOptions.NONE ),
|
||||||
final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler = SubselectFetch.createRegistrationHandler(
|
|
||||||
batchFetchQueue,
|
|
||||||
sqlAst,
|
|
||||||
JdbcParametersList.singleton( jdbcParameter ),
|
|
||||||
jdbcParameterBindings
|
|
||||||
);
|
|
||||||
|
|
||||||
session.getJdbcServices().getJdbcSelectExecutor().executeQuery(
|
|
||||||
jdbcSelectOperation,
|
|
||||||
jdbcParameterBindings,
|
jdbcParameterBindings,
|
||||||
new ExecutionContextWithSubselectFetchHandler( session,
|
new ExecutionContextWithSubselectFetchHandler(
|
||||||
subSelectFetchableKeysHandler,
|
session,
|
||||||
|
createRegistrationHandler(
|
||||||
|
session.getPersistenceContext().getBatchFetchQueue(),
|
||||||
|
sqlAst,
|
||||||
|
JdbcParametersList.singleton( jdbcParameter ),
|
||||||
|
jdbcParameterBindings
|
||||||
|
),
|
||||||
TRUE.equals( loadOptions.getReadOnly( session ) ) ),
|
TRUE.equals( loadOptions.getReadOnly( session ) ) ),
|
||||||
RowTransformerStandardImpl.instance(),
|
RowTransformerStandardImpl.instance(),
|
||||||
null,
|
null,
|
||||||
idsToLoadFromDatabase.size(),
|
idsInBatch.size(),
|
||||||
ManagedResultConsumer.INSTANCE
|
ManagedResultConsumer.INSTANCE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <K> List<E> performUnorderedMultiLoad(
|
protected <K> List<E> performUnorderedMultiLoad(
|
||||||
K[] ids,
|
K[] ids,
|
||||||
|
@ -180,7 +168,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<E> result = CollectionHelper.arrayList( ids.length );
|
final List<E> result = CollectionHelper.arrayList( ids.length );
|
||||||
final LockOptions lockOptions = (loadOptions.getLockOptions() == null)
|
final LockOptions lockOptions = loadOptions.getLockOptions() == null
|
||||||
? new LockOptions( LockMode.NONE )
|
? new LockOptions( LockMode.NONE )
|
||||||
: loadOptions.getLockOptions();
|
: loadOptions.getLockOptions();
|
||||||
|
|
||||||
|
@ -198,7 +186,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelectBySingleArrayParameter(
|
final SelectStatement sqlAst = createSelectBySingleArrayParameter(
|
||||||
getLoadable(),
|
getLoadable(),
|
||||||
getIdentifierMapping(),
|
getIdentifierMapping(),
|
||||||
session.getLoadQueryInfluencers(),
|
session.getLoadQueryInfluencers(),
|
||||||
|
@ -206,13 +194,11 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
jdbcParameter,
|
jdbcParameter,
|
||||||
getSessionFactory()
|
getSessionFactory()
|
||||||
);
|
);
|
||||||
final JdbcOperationQuerySelect jdbcSelectOperation = getSessionFactory().getJdbcServices()
|
final JdbcOperationQuerySelect jdbcSelectOperation =
|
||||||
.getJdbcEnvironment()
|
getSqlAstTranslatorFactory().buildSelectTranslator( getSessionFactory(), sqlAst )
|
||||||
.getSqlAstTranslatorFactory()
|
.translate( NO_BINDINGS, QueryOptions.NONE );
|
||||||
.buildSelectTranslator( getSessionFactory(), sqlAst )
|
|
||||||
.translate( JdbcParameterBindings.NO_BINDINGS, QueryOptions.NONE );
|
|
||||||
|
|
||||||
final List<E> databaseResults = LoaderHelper.loadByArrayParameter(
|
final List<E> databaseResults = loadByArrayParameter(
|
||||||
idsToLoadFromDatabase,
|
idsToLoadFromDatabase,
|
||||||
sqlAst,
|
sqlAst,
|
||||||
jdbcSelectOperation,
|
jdbcSelectOperation,
|
||||||
|
@ -236,7 +222,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// found or not, remove the key from the batch-fetch queue
|
// found or not, remove the key from the batch-fetch queue
|
||||||
BatchFetchQueueHelper.removeBatchLoadableEntityKey( id, getLoadable(), session );
|
removeBatchLoadableEntityKey( id, getLoadable(), session );
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -272,7 +258,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
||||||
lockOptions,
|
lockOptions,
|
||||||
session,
|
session,
|
||||||
LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session )
|
getReadOnlyFromLoadQueryInfluencers( session )
|
||||||
);
|
);
|
||||||
|
|
||||||
Object managedEntity = null;
|
Object managedEntity = null;
|
||||||
|
|
|
@ -6,11 +6,11 @@ package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
|
import org.hibernate.engine.spi.BatchFetchQueue;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.PersistenceContext;
|
import org.hibernate.engine.spi.PersistenceContext;
|
||||||
|
@ -20,26 +20,29 @@ import org.hibernate.engine.spi.SubselectFetch;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
import org.hibernate.event.spi.LoadEvent;
|
import org.hibernate.event.spi.LoadEvent;
|
||||||
import org.hibernate.event.spi.LoadEventListener;
|
import org.hibernate.event.spi.LoadEventListener;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
|
||||||
import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.PersistenceContextEntry;
|
import org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.PersistenceContextEntry;
|
||||||
import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
|
import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
|
||||||
|
import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
|
||||||
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
import org.hibernate.sql.ast.tree.select.SelectStatement;
|
||||||
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
|
||||||
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
|
||||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||||
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
import org.hibernate.sql.exec.spi.JdbcParametersList;
|
||||||
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
import org.hibernate.sql.results.internal.RowTransformerStandardImpl;
|
||||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||||
|
|
||||||
import org.hibernate.type.descriptor.java.JavaType;
|
import org.hibernate.type.descriptor.java.JavaType;
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
import static java.lang.Boolean.TRUE;
|
import static java.lang.Boolean.TRUE;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static org.hibernate.engine.spi.SubselectFetch.createRegistrationHandler;
|
||||||
|
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||||
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFromSessionCacheStatic;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderHelper.getReadOnlyFromLoadQueryInfluencers;
|
||||||
|
import static org.hibernate.loader.ast.internal.LoaderSelectBuilder.createSelect;
|
||||||
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard MultiIdEntityLoader
|
* Standard MultiIdEntityLoader
|
||||||
|
@ -47,7 +50,6 @@ import static org.hibernate.loader.ast.internal.CacheEntityLoaderHelper.loadFrom
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<T> {
|
public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<T> {
|
||||||
private static final Logger log = Logger.getLogger( MultiIdEntityLoaderStandard.class );
|
|
||||||
|
|
||||||
private final int idJdbcTypeCount;
|
private final int idJdbcTypeCount;
|
||||||
|
|
||||||
|
@ -57,10 +59,17 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
super( entityDescriptor, sessionFactory );
|
super( entityDescriptor, sessionFactory );
|
||||||
this.idJdbcTypeCount = idColumnSpan;
|
this.idJdbcTypeCount = idColumnSpan;
|
||||||
|
|
||||||
assert idJdbcTypeCount > 0;
|
assert idJdbcTypeCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isInClauseParameterPaddingEnabled() {
|
||||||
|
return getSessionFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiKeyLoadSizingStrategy getBatchLoadSizingStrategy() {
|
||||||
|
return getJdbcServices().getJdbcEnvironment().getDialect().getBatchLoadSizingStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleResults(
|
protected void handleResults(
|
||||||
MultiIdLoadOptions loadOptions,
|
MultiIdLoadOptions loadOptions,
|
||||||
|
@ -90,17 +99,12 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions) {
|
protected int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions) {
|
||||||
if ( loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0 ) {
|
final Integer explicitBatchSize = loadOptions.getBatchSize();
|
||||||
return loadOptions.getBatchSize();
|
return explicitBatchSize != null && explicitBatchSize > 0
|
||||||
}
|
? explicitBatchSize
|
||||||
else {
|
: getBatchLoadSizingStrategy()
|
||||||
return getSessionFactory().getJdbcServices().getJdbcEnvironment().getDialect()
|
.determineOptimalBatchLoadSize( idJdbcTypeCount, ids.length,
|
||||||
.getBatchLoadSizingStrategy().determineOptimalBatchLoadSize(
|
isInClauseParameterPaddingEnabled() );
|
||||||
idJdbcTypeCount,
|
|
||||||
ids.length,
|
|
||||||
getSessionFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -111,7 +115,6 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
EventSource session) {
|
EventSource session) {
|
||||||
assert idsInBatch != null;
|
assert idsInBatch != null;
|
||||||
assert !idsInBatch.isEmpty();
|
assert !idsInBatch.isEmpty();
|
||||||
|
|
||||||
listEntitiesById( idsInBatch, lockOptions, loadOptions, session );
|
listEntitiesById( idsInBatch, lockOptions, loadOptions, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,85 +124,84 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
MultiIdLoadOptions loadOptions,
|
MultiIdLoadOptions loadOptions,
|
||||||
EventSource session) {
|
EventSource session) {
|
||||||
final int numberOfIdsInBatch = idsInBatch.size();
|
final int numberOfIdsInBatch = idsInBatch.size();
|
||||||
if ( numberOfIdsInBatch == 1 ) {
|
return numberOfIdsInBatch == 1
|
||||||
return performSingleMultiLoad( idsInBatch.get( 0 ), lockOptions, session );
|
? performSingleMultiLoad( idsInBatch.get( 0 ), lockOptions, session )
|
||||||
|
: performRegularMultiLoad( idsInBatch, lockOptions, loadOptions, session, numberOfIdsInBatch );
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<T> performRegularMultiLoad(
|
||||||
|
List<Object> idsInBatch,
|
||||||
|
LockOptions lockOptions,
|
||||||
|
MultiIdLoadOptions loadOptions,
|
||||||
|
EventSource session,
|
||||||
|
int numberOfIdsInBatch) {
|
||||||
|
if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) {
|
||||||
|
MULTI_KEY_LOAD_LOGGER.tracef( "#loadEntitiesById(`%s`, `%s`, ..)",
|
||||||
|
getLoadable().getEntityName(), numberOfIdsInBatch );
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if ( log.isTraceEnabled() ) {
|
|
||||||
log.tracef( "#loadEntitiesById(`%s`, `%s`, ..)", getLoadable().getEntityName(), numberOfIdsInBatch );
|
|
||||||
}
|
|
||||||
|
|
||||||
final JdbcParametersList.Builder jdbcParametersBuilder =
|
final JdbcParametersList.Builder jdbcParametersBuilder =
|
||||||
JdbcParametersList.newBuilder( numberOfIdsInBatch * idJdbcTypeCount );
|
JdbcParametersList.newBuilder( numberOfIdsInBatch * idJdbcTypeCount );
|
||||||
|
|
||||||
final SelectStatement sqlAst = LoaderSelectBuilder.createSelect(
|
final SelectStatement sqlAst = createSelect(
|
||||||
getLoadable(),
|
getLoadable(),
|
||||||
// null here means to select everything
|
// null here means to select everything
|
||||||
null,
|
null,
|
||||||
|
getLoadable().getIdentifierMapping(),
|
||||||
|
null,
|
||||||
|
numberOfIdsInBatch,
|
||||||
|
session.getLoadQueryInfluencers(),
|
||||||
|
lockOptions,
|
||||||
|
jdbcParametersBuilder::add,
|
||||||
|
getSessionFactory()
|
||||||
|
);
|
||||||
|
|
||||||
|
final JdbcParametersList jdbcParameters = jdbcParametersBuilder.build();
|
||||||
|
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
||||||
|
int offset = 0;
|
||||||
|
for ( int i = 0; i < numberOfIdsInBatch; i++ ) {
|
||||||
|
offset += jdbcParameterBindings.registerParametersForEachJdbcValue(
|
||||||
|
idsInBatch.get( i ),
|
||||||
|
offset,
|
||||||
getLoadable().getIdentifierMapping(),
|
getLoadable().getIdentifierMapping(),
|
||||||
null,
|
jdbcParameters,
|
||||||
numberOfIdsInBatch,
|
session
|
||||||
session.getLoadQueryInfluencers(),
|
|
||||||
lockOptions,
|
|
||||||
jdbcParametersBuilder::add,
|
|
||||||
getSessionFactory()
|
|
||||||
);
|
|
||||||
JdbcParametersList jdbcParameters = jdbcParametersBuilder.build();
|
|
||||||
|
|
||||||
final SqlAstTranslatorFactory sqlAstTranslatorFactory =
|
|
||||||
getSessionFactory().getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory();
|
|
||||||
|
|
||||||
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( jdbcParameters.size() );
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
for ( int i = 0; i < numberOfIdsInBatch; i++ ) {
|
|
||||||
final Object id = idsInBatch.get( i );
|
|
||||||
|
|
||||||
offset += jdbcParameterBindings.registerParametersForEachJdbcValue(
|
|
||||||
id,
|
|
||||||
offset,
|
|
||||||
getLoadable().getIdentifierMapping(),
|
|
||||||
jdbcParameters,
|
|
||||||
session
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we should have used all the JdbcParameter references (created bindings for all)
|
|
||||||
assert offset == jdbcParameters.size();
|
|
||||||
final JdbcOperationQuerySelect jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( getSessionFactory(), sqlAst )
|
|
||||||
.translate( jdbcParameterBindings, QueryOptions.NONE );
|
|
||||||
|
|
||||||
final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler;
|
|
||||||
if ( session.getLoadQueryInfluencers().hasSubselectLoadableCollections( getLoadable().getEntityPersister() ) ) {
|
|
||||||
subSelectFetchableKeysHandler = SubselectFetch.createRegistrationHandler(
|
|
||||||
session.getPersistenceContext().getBatchFetchQueue(),
|
|
||||||
sqlAst,
|
|
||||||
jdbcParameters,
|
|
||||||
jdbcParameterBindings
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
subSelectFetchableKeysHandler = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return session.getJdbcServices().getJdbcSelectExecutor().list(
|
|
||||||
jdbcSelect,
|
|
||||||
jdbcParameterBindings,
|
|
||||||
new ExecutionContextWithSubselectFetchHandler( session,
|
|
||||||
subSelectFetchableKeysHandler,
|
|
||||||
TRUE.equals( loadOptions.getReadOnly( session ) ) ),
|
|
||||||
RowTransformerStandardImpl.instance(),
|
|
||||||
null,
|
|
||||||
ListResultsConsumer.UniqueSemantic.FILTER,
|
|
||||||
idsInBatch.size()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// we should have used all the JdbcParameter references (created bindings for all)
|
||||||
|
assert offset == jdbcParameters.size();
|
||||||
|
|
||||||
|
return getJdbcSelectExecutor().list(
|
||||||
|
getSqlAstTranslatorFactory().buildSelectTranslator( getSessionFactory(), sqlAst )
|
||||||
|
.translate( jdbcParameterBindings, QueryOptions.NONE ),
|
||||||
|
jdbcParameterBindings,
|
||||||
|
new ExecutionContextWithSubselectFetchHandler(
|
||||||
|
session,
|
||||||
|
fetchableKeysHandler( session, sqlAst, jdbcParameters, jdbcParameterBindings ),
|
||||||
|
TRUE.equals( loadOptions.getReadOnly( session ) )
|
||||||
|
),
|
||||||
|
RowTransformerStandardImpl.instance(),
|
||||||
|
null,
|
||||||
|
ListResultsConsumer.UniqueSemantic.FILTER,
|
||||||
|
idsInBatch.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SubselectFetch.RegistrationHandler fetchableKeysHandler(
|
||||||
|
EventSource session,
|
||||||
|
SelectStatement sqlAst,
|
||||||
|
JdbcParametersList jdbcParameters,
|
||||||
|
JdbcParameterBindings jdbcParameterBindings) {
|
||||||
|
final BatchFetchQueue batchFetchQueue = session.getPersistenceContext().getBatchFetchQueue();
|
||||||
|
return session.getLoadQueryInfluencers().hasSubselectLoadableCollections( getLoadable().getEntityPersister() )
|
||||||
|
? createRegistrationHandler( batchFetchQueue, sqlAst, jdbcParameters, jdbcParameterBindings )
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<T> performSingleMultiLoad(Object id, LockOptions lockOptions, SharedSessionContractImplementor session) {
|
private List<T> performSingleMultiLoad(Object id, LockOptions lockOptions, SharedSessionContractImplementor session) {
|
||||||
//noinspection unchecked
|
@SuppressWarnings("unchecked")
|
||||||
T loaded = (T) getLoadable().getEntityPersister().load( id, null, lockOptions, session );
|
T loaded = (T) getLoadable().getEntityPersister().load( id, null, lockOptions, session );
|
||||||
return Collections.singletonList( loaded );
|
return singletonList( loaded );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -210,11 +212,11 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
assert !loadOptions.isOrderReturnEnabled();
|
assert !loadOptions.isOrderReturnEnabled();
|
||||||
assert ids != null;
|
assert ids != null;
|
||||||
|
|
||||||
if ( log.isTraceEnabled() ) {
|
if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) {
|
||||||
log.tracef( "#performUnorderedMultiLoad(`%s`, ..)", getLoadable().getEntityName() );
|
MULTI_KEY_LOAD_LOGGER.tracef( "#performUnorderedMultiLoad(`%s`, ..)", getLoadable().getEntityName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<T> result = CollectionHelper.arrayList( ids.length );
|
final List<T> result = arrayList( ids.length );
|
||||||
|
|
||||||
final LockOptions lockOptions = loadOptions.getLockOptions() == null
|
final LockOptions lockOptions = loadOptions.getLockOptions() == null
|
||||||
? new LockOptions( LockMode.NONE )
|
? new LockOptions( LockMode.NONE )
|
||||||
|
@ -241,7 +243,7 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
getLoadable().getJavaType().getJavaTypeClass().getName(),
|
||||||
lockOptions,
|
lockOptions,
|
||||||
session,
|
session,
|
||||||
LoaderHelper.getReadOnlyFromLoadQueryInfluencers( session )
|
getReadOnlyFromLoadQueryInfluencers( session )
|
||||||
);
|
);
|
||||||
|
|
||||||
Object managedEntity = null;
|
Object managedEntity = null;
|
||||||
|
@ -303,27 +305,23 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
maxBatchSize = loadOptions.getBatchSize();
|
maxBatchSize = loadOptions.getBatchSize();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
maxBatchSize = session.getJdbcServices().getJdbcEnvironment().getDialect().getBatchLoadSizingStrategy().determineOptimalBatchLoadSize(
|
maxBatchSize = getBatchLoadSizingStrategy().determineOptimalBatchLoadSize(
|
||||||
getIdentifierMapping().getJdbcTypeCount(),
|
getIdentifierMapping().getJdbcTypeCount(),
|
||||||
numberOfIdsLeft,
|
numberOfIdsLeft,
|
||||||
getSessionFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled()
|
isInClauseParameterPaddingEnabled()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int idPosition = 0;
|
int idPosition = 0;
|
||||||
while ( numberOfIdsLeft > 0 ) {
|
while ( numberOfIdsLeft > 0 ) {
|
||||||
final int batchSize = Math.min( numberOfIdsLeft, maxBatchSize );
|
final int batchSize = Math.min( numberOfIdsLeft, maxBatchSize );
|
||||||
|
|
||||||
final Object[] idsInBatch = new Object[ batchSize ];
|
final Object[] idsInBatch = new Object[ batchSize ];
|
||||||
System.arraycopy( ids, idPosition, idsInBatch, 0, batchSize );
|
System.arraycopy( ids, idPosition, idsInBatch, 0, batchSize );
|
||||||
|
|
||||||
result.addAll( listEntitiesById( asList( idsInBatch ), lockOptions, loadOptions, session ) );
|
result.addAll( listEntitiesById( asList( idsInBatch ), lockOptions, loadOptions, session ) );
|
||||||
|
|
||||||
numberOfIdsLeft = numberOfIdsLeft - batchSize;
|
numberOfIdsLeft = numberOfIdsLeft - batchSize;
|
||||||
idPosition += batchSize;
|
idPosition += batchSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -857,7 +857,7 @@ public abstract class AbstractEntityPersister
|
||||||
protected MultiIdEntityLoader<Object> buildMultiIdLoader() {
|
protected MultiIdEntityLoader<Object> buildMultiIdLoader() {
|
||||||
final Dialect dialect = factory.getJdbcServices().getDialect();
|
final Dialect dialect = factory.getJdbcServices().getDialect();
|
||||||
return getIdentifierType() instanceof BasicType && supportsSqlArrayType( dialect )
|
return getIdentifierType() instanceof BasicType && supportsSqlArrayType( dialect )
|
||||||
? new MultiIdEntityLoaderArrayParam<>( this, identifierColumnSpan, factory )
|
? new MultiIdEntityLoaderArrayParam<>( this, factory )
|
||||||
: new MultiIdEntityLoaderStandard<>( this, identifierColumnSpan, factory );
|
: new MultiIdEntityLoaderStandard<>( this, identifierColumnSpan, factory );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue