HHH-16651 make persisters return adapted loaders for session batch size
This commit is contained in:
parent
3097c47b3d
commit
bbd8df93ca
|
@ -46,7 +46,7 @@ public class CollectionLoaderSubSelectFetch implements CollectionLoader {
|
||||||
|
|
||||||
public CollectionLoaderSubSelectFetch(
|
public CollectionLoaderSubSelectFetch(
|
||||||
PluralAttributeMapping attributeMapping,
|
PluralAttributeMapping attributeMapping,
|
||||||
DomainResult cachedDomainResult,
|
DomainResult<?> cachedDomainResult,
|
||||||
SubselectFetch subselect,
|
SubselectFetch subselect,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
this.attributeMapping = attributeMapping;
|
this.attributeMapping = attributeMapping;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
|
@ -16,7 +15,6 @@ import org.hibernate.engine.spi.EntityKey;
|
||||||
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.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.engine.spi.SubselectFetch;
|
|
||||||
import org.hibernate.loader.ast.spi.EntityBatchLoader;
|
import org.hibernate.loader.ast.spi.EntityBatchLoader;
|
||||||
import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader;
|
import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader;
|
||||||
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
import org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping;
|
||||||
|
@ -26,15 +24,9 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||||
import org.hibernate.query.spi.QueryOptions;
|
import org.hibernate.query.spi.QueryOptions;
|
||||||
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.JdbcParameterBindingsImpl;
|
|
||||||
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
|
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.results.internal.RowTransformerStandardImpl;
|
|
||||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
|
||||||
import org.hibernate.type.BasicType;
|
|
||||||
import org.hibernate.type.BasicTypeRegistry;
|
|
||||||
|
|
||||||
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED;
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_DEBUG_ENABLED;
|
||||||
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER;
|
||||||
|
@ -162,13 +154,10 @@ public class EntityBatchLoaderArrayParam<T>
|
||||||
@Override
|
@Override
|
||||||
public void prepare() {
|
public void prepare() {
|
||||||
identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping();
|
identifierMapping = (BasicEntityIdentifierMapping) getLoadable().getIdentifierMapping();
|
||||||
final Class<?> arrayClass = Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass();
|
final Class<?> arrayClass =
|
||||||
|
Array.newInstance( identifierMapping.getJavaType().getJavaTypeClass(), 0 ).getClass();
|
||||||
final BasicTypeRegistry basicTypeRegistry = sessionFactory.getTypeConfiguration().getBasicTypeRegistry();
|
|
||||||
final BasicType<?> arrayBasicType = basicTypeRegistry.getRegisteredType( arrayClass );
|
|
||||||
|
|
||||||
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
|
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
|
||||||
arrayBasicType,
|
sessionFactory.getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
|
||||||
identifierMapping.getJdbcMapping(),
|
identifierMapping.getJdbcMapping(),
|
||||||
arrayClass,
|
arrayClass,
|
||||||
sessionFactory
|
sessionFactory
|
||||||
|
|
|
@ -56,16 +56,18 @@ public class EntityBatchLoaderInPredicate<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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}
|
||||||
* @param sqlBatchSize The number of keys our SQL AST should be able to fetch
|
|
||||||
*/
|
*/
|
||||||
public EntityBatchLoaderInPredicate(
|
public EntityBatchLoaderInPredicate(
|
||||||
int domainBatchSize,
|
int domainBatchSize,
|
||||||
int sqlBatchSize,
|
|
||||||
EntityMappingType entityDescriptor,
|
EntityMappingType entityDescriptor,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
super( entityDescriptor, sessionFactory );
|
super( entityDescriptor, sessionFactory );
|
||||||
this.domainBatchSize = domainBatchSize;
|
this.domainBatchSize = domainBatchSize;
|
||||||
this.sqlBatchSize = sqlBatchSize;
|
int idColumnCount = entityDescriptor.getEntityPersister().getIdentifierType().getColumnSpan( sessionFactory );
|
||||||
|
this.sqlBatchSize = sessionFactory.getJdbcServices()
|
||||||
|
.getDialect()
|
||||||
|
.getBatchLoadSizingStrategy()
|
||||||
|
.determineOptimalBatchLoadSize( idColumnCount, domainBatchSize, false );
|
||||||
|
|
||||||
if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) {
|
if ( MULTI_KEY_LOAD_DEBUG_ENABLED ) {
|
||||||
MULTI_KEY_LOAD_LOGGER.debugf(
|
MULTI_KEY_LOAD_LOGGER.debugf(
|
||||||
|
|
|
@ -40,8 +40,6 @@ 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.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.BasicType;
|
|
||||||
import org.hibernate.type.BasicTypeRegistry;
|
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
|
@ -385,7 +383,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <X> X[] createTypedArray(@SuppressWarnings("SameParameterValue") int length) {
|
private <X> X[] createTypedArray(@SuppressWarnings("SameParameterValue") int length) {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return (X[]) Array.newInstance( getIdentifierMapping().getJavaType().getJavaTypeClass(), length );
|
return (X[]) Array.newInstance( getIdentifierMapping().getJavaType().getJavaTypeClass(), length );
|
||||||
}
|
}
|
||||||
|
@ -393,14 +391,9 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
||||||
@Override
|
@Override
|
||||||
public void prepare() {
|
public void prepare() {
|
||||||
super.prepare();
|
super.prepare();
|
||||||
|
|
||||||
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
|
final Class<?> arrayClass = createTypedArray( 0 ).getClass();
|
||||||
|
|
||||||
final BasicTypeRegistry basicTypeRegistry = getSessionFactory().getTypeConfiguration().getBasicTypeRegistry();
|
|
||||||
final BasicType<?> arrayBasicType = basicTypeRegistry.getRegisteredType( arrayClass );
|
|
||||||
|
|
||||||
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
|
arrayJdbcMapping = MultiKeyLoadHelper.resolveArrayJdbcMapping(
|
||||||
arrayBasicType,
|
getSessionFactory().getTypeConfiguration().getBasicTypeRegistry().getRegisteredType( arrayClass ),
|
||||||
getIdentifierMapping().getJdbcMapping(),
|
getIdentifierMapping().getJdbcMapping(),
|
||||||
arrayClass,
|
arrayClass,
|
||||||
getSessionFactory()
|
getSessionFactory()
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.LockMode;
|
||||||
import org.hibernate.LockOptions;
|
import org.hibernate.LockOptions;
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
|
||||||
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;
|
||||||
|
@ -28,7 +27,6 @@ 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.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
|
import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
|
||||||
import org.hibernate.mapping.PersistentClass;
|
|
||||||
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.SqlAstTranslatorFactory;
|
||||||
|
@ -54,10 +52,10 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
||||||
|
|
||||||
public MultiIdEntityLoaderStandard(
|
public MultiIdEntityLoaderStandard(
|
||||||
EntityPersister entityDescriptor,
|
EntityPersister entityDescriptor,
|
||||||
PersistentClass bootDescriptor,
|
int idColumnSpan,
|
||||||
SessionFactoryImplementor sessionFactory) {
|
SessionFactoryImplementor sessionFactory) {
|
||||||
super( entityDescriptor, sessionFactory );
|
super( entityDescriptor, sessionFactory );
|
||||||
this.idJdbcTypeCount = bootDescriptor.getIdentifier().getColumnSpan();
|
this.idJdbcTypeCount = idColumnSpan;
|
||||||
|
|
||||||
assert idJdbcTypeCount > 0;
|
assert idJdbcTypeCount > 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,10 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SqlTypes;
|
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.supportsSqlArrayType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard {@link BatchLoaderFactory} implementation
|
* Standard {@link BatchLoaderFactory} implementation
|
||||||
*
|
*
|
||||||
|
@ -35,23 +36,18 @@ public class StandardBatchLoaderFactory implements BatchLoaderFactory {
|
||||||
public <T> EntityBatchLoader<T> createEntityBatchLoader(
|
public <T> EntityBatchLoader<T> createEntityBatchLoader(
|
||||||
int domainBatchSize, EntityMappingType entityDescriptor,
|
int domainBatchSize, EntityMappingType entityDescriptor,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
final Dialect dialect = factory.getJdbcServices().getDialect();
|
|
||||||
|
|
||||||
// NOTE : don't use the EntityIdentifierMapping here because it will not be known until later
|
// NOTE : don't use the EntityIdentifierMapping here because it will not be known until later
|
||||||
final Type identifierType = entityDescriptor.getEntityPersister().getIdentifierType();
|
final Type identifierType = entityDescriptor.getEntityPersister().getIdentifierType();
|
||||||
final int idColumnCount = identifierType.getColumnSpan( factory );
|
if ( identifierType.getColumnSpan( factory ) == 1
|
||||||
|
&& supportsSqlArrayType( factory.getJdbcServices().getDialect() )
|
||||||
if ( idColumnCount == 1
|
|
||||||
&& MultiKeyLoadHelper.supportsSqlArrayType( dialect )
|
|
||||||
&& identifierType instanceof BasicType ) {
|
&& identifierType instanceof BasicType ) {
|
||||||
// we can use a single ARRAY parameter to send all the ids
|
// we can use a single ARRAY parameter to send all the ids
|
||||||
return new EntityBatchLoaderArrayParam<>( domainBatchSize, entityDescriptor, factory );
|
return new EntityBatchLoaderArrayParam<>( domainBatchSize, entityDescriptor, factory );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
final int optimalBatchSize = dialect
|
return new EntityBatchLoaderInPredicate<>( domainBatchSize, entityDescriptor, factory );
|
||||||
.getBatchLoadSizingStrategy()
|
}
|
||||||
.determineOptimalBatchLoadSize( idColumnCount, domainBatchSize, false );
|
|
||||||
return new EntityBatchLoaderInPredicate<>( domainBatchSize, optimalBatchSize, entityDescriptor, factory );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,15 +56,13 @@ public class StandardBatchLoaderFactory implements BatchLoaderFactory {
|
||||||
LoadQueryInfluencers influencers,
|
LoadQueryInfluencers influencers,
|
||||||
PluralAttributeMapping attributeMapping,
|
PluralAttributeMapping attributeMapping,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory) {
|
||||||
final Dialect dialect = factory.getJdbcServices().getDialect();
|
if ( attributeMapping.getKeyDescriptor().getJdbcTypeCount() == 1
|
||||||
final int columnCount = attributeMapping.getKeyDescriptor().getJdbcTypeCount();
|
&& supportsSqlArrayType( factory.getJdbcServices().getDialect() ) ) {
|
||||||
if ( columnCount == 1
|
|
||||||
&& dialect.supportsStandardArrays()
|
|
||||||
&& dialect.getPreferredSqlTypeCodeForArray() == SqlTypes.ARRAY ) {
|
|
||||||
// we can use a single ARRAY parameter to send all the ids
|
// we can use a single ARRAY parameter to send all the ids
|
||||||
return new CollectionBatchLoaderArrayParam( domainBatchSize, influencers, attributeMapping, factory );
|
return new CollectionBatchLoaderArrayParam( domainBatchSize, influencers, attributeMapping, factory );
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
return new CollectionBatchLoaderInPredicate( domainBatchSize, influencers, attributeMapping, factory );
|
return new CollectionBatchLoaderInPredicate( domainBatchSize, influencers, attributeMapping, factory );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,21 @@ public interface Loadable extends ModelPart, RootTableGroupProducer {
|
||||||
|
|
||||||
default boolean isAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
default boolean isAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
||||||
return isAffectedByEntityGraph( influencers )
|
return isAffectedByEntityGraph( influencers )
|
||||||
|| isAffectedByEnabledFetchProfiles( influencers )
|
|| isAffectedByEnabledFetchProfiles( influencers )
|
||||||
|| isAffectedByEnabledFilters( influencers );
|
|| isAffectedByEnabledFilters( influencers )
|
||||||
|
|| influencers.getBatchSize() != getBatchSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isNotAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
default boolean isNotAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
||||||
return !isAffectedByEntityGraph( influencers )
|
return !isAffectedByEntityGraph( influencers )
|
||||||
&& !isAffectedByEnabledFetchProfiles( influencers )
|
&& !isAffectedByEnabledFetchProfiles( influencers )
|
||||||
&& !isAffectedByEnabledFilters( influencers )
|
&& !isAffectedByEnabledFilters( influencers )
|
||||||
&& influencers.getEnabledCascadingFetchProfile() == null;
|
&& influencers.getBatchSize() == getBatchSize()
|
||||||
|
&& influencers.getEnabledCascadingFetchProfile() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getBatchSize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether any of the "influencers" affect this loadable.
|
* Whether any of the "influencers" affect this loadable.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -885,6 +885,11 @@ public class PluralAttributeMappingImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBatchSize() {
|
||||||
|
return getCollectionDescriptor().getBatchSize();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
||||||
return getCollectionDescriptor().isAffectedByEnabledFilters( influencers );
|
return getCollectionDescriptor().isAffectedByEnabledFilters( influencers );
|
||||||
|
|
|
@ -6,17 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.persister.collection;
|
package org.hibernate.persister.collection;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.Filter;
|
import org.hibernate.Filter;
|
||||||
|
@ -27,6 +16,7 @@ import org.hibernate.MappingException;
|
||||||
import org.hibernate.QueryException;
|
import org.hibernate.QueryException;
|
||||||
import org.hibernate.Remove;
|
import org.hibernate.Remove;
|
||||||
import org.hibernate.TransientObjectException;
|
import org.hibernate.TransientObjectException;
|
||||||
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.cache.CacheException;
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
import org.hibernate.cache.spi.access.CollectionDataAccess;
|
||||||
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
import org.hibernate.cache.spi.entry.CacheEntryStructure;
|
||||||
|
@ -124,7 +114,6 @@ import org.hibernate.sql.model.ast.RestrictedTableMutation;
|
||||||
import org.hibernate.sql.model.internal.TableDeleteStandard;
|
import org.hibernate.sql.model.internal.TableDeleteStandard;
|
||||||
import org.hibernate.sql.model.jdbc.JdbcDeleteMutation;
|
import org.hibernate.sql.model.jdbc.JdbcDeleteMutation;
|
||||||
import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
|
import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
|
||||||
import org.hibernate.sql.results.graph.DomainResult;
|
|
||||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
|
@ -132,6 +121,17 @@ import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||||
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
|
import static org.hibernate.sql.model.ModelMutationLogging.MODEL_MUTATION_LOGGER;
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ public abstract class AbstractCollectionPersister
|
||||||
private final Comparator<?> comparator;
|
private final Comparator<?> comparator;
|
||||||
|
|
||||||
private CollectionLoader collectionLoader;
|
private CollectionLoader collectionLoader;
|
||||||
private volatile CollectionLoader standardCollectionLoader;
|
// private volatile CollectionLoader standardCollectionLoader;
|
||||||
private CollectionElementLoaderByIndex collectionElementLoaderByIndex;
|
private CollectionElementLoaderByIndex collectionElementLoaderByIndex;
|
||||||
|
|
||||||
private PluralAttributeMapping attributeMapping;
|
private PluralAttributeMapping attributeMapping;
|
||||||
|
@ -570,14 +570,8 @@ public abstract class AbstractCollectionPersister
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// "mapping model"
|
// "mapping model"
|
||||||
|
|
||||||
if ( queryLoaderName != null ) {
|
if ( hasNamedQueryLoader() ) {
|
||||||
final NamedQueryMemento namedQueryMemento = factory
|
getNamedQueryMemento( collectionBootDescriptor.getMetadata() );
|
||||||
.getQueryEngine()
|
|
||||||
.getNamedObjectRepository()
|
|
||||||
.resolve( factory, collectionBootDescriptor.getMetadata(), queryLoaderName );
|
|
||||||
if ( namedQueryMemento == null ) {
|
|
||||||
throw new IllegalArgumentException( "Could not resolve named load-query [" + navigableRole + "] : " + queryLoaderName );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tableMapping = buildCollectionTableMapping( collectionBootDescriptor, getTableName(), getCollectionSpaces() );
|
tableMapping = buildCollectionTableMapping( collectionBootDescriptor, getTableName(), getCollectionSpaces() );
|
||||||
|
@ -614,14 +608,12 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInstantiate() throws MappingException {
|
public void postInstantiate() throws MappingException {
|
||||||
if ( queryLoaderName == null ) {
|
if ( hasNamedQueryLoader() ) {
|
||||||
collectionLoader = createCollectionLoader( new LoadQueryInfluencers( factory ) );
|
// We pass null as metamodel because we did the initialization during construction already
|
||||||
|
collectionLoader = new CollectionLoaderNamedQuery( this, getNamedQueryMemento( null ) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We pass null as metamodel because we did the initialization during construction already
|
collectionLoader = createCollectionLoader( new LoadQueryInfluencers( factory ) );
|
||||||
final NamedQueryMemento namedQueryMemento = factory.getQueryEngine().getNamedObjectRepository()
|
|
||||||
.resolve( factory, null, queryLoaderName );
|
|
||||||
collectionLoader = new CollectionLoaderNamedQuery( this, namedQueryMemento );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( attributeMapping.getIndexDescriptor() != null ) {
|
if ( attributeMapping.getIndexDescriptor() != null ) {
|
||||||
|
@ -635,6 +627,17 @@ public abstract class AbstractCollectionPersister
|
||||||
logStaticSQL();
|
logStaticSQL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NamedQueryMemento getNamedQueryMemento(MetadataImplementor bootModel) {
|
||||||
|
final NamedQueryMemento memento =
|
||||||
|
factory.getQueryEngine().getNamedObjectRepository()
|
||||||
|
.resolve( factory, bootModel, queryLoaderName );
|
||||||
|
if ( memento == null ) {
|
||||||
|
throw new IllegalArgumentException( "Could not resolve named query '" + queryLoaderName
|
||||||
|
+ "' for loading collection '" + getName() + "'" );
|
||||||
|
}
|
||||||
|
return memento;
|
||||||
|
}
|
||||||
|
|
||||||
protected void logStaticSQL() {
|
protected void logStaticSQL() {
|
||||||
if ( !ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) {
|
if ( !ModelMutationLogging.MODEL_MUTATION_LOGGER_DEBUG_ENABLED ) {
|
||||||
return;
|
return;
|
||||||
|
@ -676,51 +679,50 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
// lazily initialize instance field via 'double-checked locking'
|
// lazily initialize instance field via 'double-checked locking'
|
||||||
// see https://en.wikipedia.org/wiki/Double-checked_locking on why 'volatile' and local copy is used
|
// see https://en.wikipedia.org/wiki/Double-checked_locking on why 'volatile' and local copy is used
|
||||||
protected CollectionLoader getStandardCollectionLoader() {
|
// protected CollectionLoader getStandardCollectionLoader() {
|
||||||
CollectionLoader localCopy = standardCollectionLoader;
|
// CollectionLoader localCopy = standardCollectionLoader;
|
||||||
if ( localCopy == null ) {
|
// if ( localCopy == null ) {
|
||||||
synchronized (this) {
|
// synchronized (this) {
|
||||||
localCopy = standardCollectionLoader;
|
// localCopy = standardCollectionLoader;
|
||||||
if ( localCopy == null ) {
|
// if ( localCopy == null ) {
|
||||||
if ( queryLoaderName != null ) {
|
// localCopy = createCollectionLoader( new LoadQueryInfluencers( factory ) );
|
||||||
localCopy = collectionLoader;
|
// standardCollectionLoader = localCopy;
|
||||||
}
|
// }
|
||||||
else {
|
// }
|
||||||
localCopy = createCollectionLoader( new LoadQueryInfluencers( factory ) );
|
// }
|
||||||
}
|
// return localCopy;
|
||||||
standardCollectionLoader = localCopy;
|
// }
|
||||||
}
|
|
||||||
}
|
private boolean hasNamedQueryLoader() {
|
||||||
}
|
return queryLoaderName != null;
|
||||||
return localCopy;
|
}
|
||||||
|
|
||||||
|
public CollectionLoader getCollectionLoader() {
|
||||||
|
return collectionLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CollectionLoader determineLoaderToUse(Object key, SharedSessionContractImplementor session) {
|
protected CollectionLoader determineLoaderToUse(Object key, SharedSessionContractImplementor session) {
|
||||||
if ( queryLoaderName != null ) {
|
if ( hasNamedQueryLoader() ) {
|
||||||
// if there is a user-specified loader, return that
|
// if there is a user-specified loader, return that
|
||||||
return getStandardCollectionLoader();
|
return getCollectionLoader();
|
||||||
}
|
}
|
||||||
final LoadQueryInfluencers loadQueryInfluencers = session.getLoadQueryInfluencers();
|
|
||||||
|
|
||||||
if ( loadQueryInfluencers.effectiveSubselectFetchEnabled( this ) ) {
|
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
|
||||||
|
|
||||||
|
if ( influencers.effectiveSubselectFetchEnabled( this ) ) {
|
||||||
final CollectionLoader subSelectLoader = resolveSubSelectLoader( key, session );
|
final CollectionLoader subSelectLoader = resolveSubSelectLoader( key, session );
|
||||||
if ( subSelectLoader != null ) {
|
if ( subSelectLoader != null ) {
|
||||||
return subSelectLoader;
|
return subSelectLoader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !loadQueryInfluencers.hasEnabledFilters()
|
return attributeMapping.isAffectedByInfluencers( influencers )
|
||||||
&& !isAffectedByEnabledFetchProfiles( loadQueryInfluencers ) ) {
|
? createCollectionLoader( influencers )
|
||||||
return getStandardCollectionLoader();
|
: getCollectionLoader();
|
||||||
}
|
|
||||||
else {
|
|
||||||
return createCollectionLoader( loadQueryInfluencers );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CollectionLoader resolveSubSelectLoader(Object key, SharedSessionContractImplementor session) {
|
private CollectionLoader resolveSubSelectLoader(Object key, SharedSessionContractImplementor session) {
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
|
|
||||||
final SubselectFetch subselect =
|
final SubselectFetch subselect =
|
||||||
persistenceContext.getBatchFetchQueue()
|
persistenceContext.getBatchFetchQueue()
|
||||||
.getSubselect( session.generateEntityKey( key, getOwnerEntityPersister() ) );
|
.getSubselect( session.generateEntityKey( key, getOwnerEntityPersister() ) );
|
||||||
|
@ -728,50 +730,47 @@ public abstract class AbstractCollectionPersister
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Take care of any entities that might have
|
// Remove keys of any entities that have been evicted
|
||||||
// been evicted!
|
|
||||||
subselect.getResultingEntityKeys()
|
subselect.getResultingEntityKeys()
|
||||||
.removeIf( entityKey -> !persistenceContext.containsEntity( entityKey ) );
|
.removeIf( entityKey -> !persistenceContext.containsEntity( entityKey ) );
|
||||||
|
|
||||||
// Run a subquery loader
|
// Run a subquery loader
|
||||||
return createSubSelectLoader( subselect, session );
|
return createSubSelectLoader( subselect, session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected CollectionLoader createSubSelectLoader(SubselectFetch subselect, SharedSessionContractImplementor session) {
|
protected CollectionLoader createSubSelectLoader(SubselectFetch subselect, SharedSessionContractImplementor session) {
|
||||||
//noinspection RedundantCast
|
return new CollectionLoaderSubSelectFetch( attributeMapping, null, subselect, session );
|
||||||
return new CollectionLoaderSubSelectFetch( attributeMapping, (DomainResult<?>) null, subselect, session );
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// private CollectionLoader reusableCollectionLoader;
|
||||||
|
//
|
||||||
|
// protected CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
// if ( canUseReusableCollectionLoader( loadQueryInfluencers ) ) {
|
||||||
|
// if ( reusableCollectionLoader == null ) {
|
||||||
|
// reusableCollectionLoader = generateCollectionLoader( new LoadQueryInfluencers( factory ) );
|
||||||
|
// }
|
||||||
|
// return reusableCollectionLoader;
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// // create a one-off
|
||||||
|
// return generateCollectionLoader( loadQueryInfluencers );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private boolean canUseReusableCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
// // we can reuse it so long as none of the enabled influencers affect it
|
||||||
|
// return attributeMapping.isNotAffectedByInfluencers( loadQueryInfluencers );
|
||||||
|
// }
|
||||||
|
|
||||||
private CollectionLoader reusableCollectionLoader;
|
private CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
|
|
||||||
protected CollectionLoader createCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
|
||||||
if ( canUseReusableCollectionLoader( loadQueryInfluencers ) ) {
|
|
||||||
if ( reusableCollectionLoader == null ) {
|
|
||||||
reusableCollectionLoader = generateCollectionLoader( new LoadQueryInfluencers( factory ) );
|
|
||||||
}
|
|
||||||
return reusableCollectionLoader;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// create a one-off
|
|
||||||
return generateCollectionLoader( loadQueryInfluencers );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canUseReusableCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
|
||||||
// we can reuse it so long as none of the enabled influencers affect it
|
|
||||||
return attributeMapping.isNotAffectedByInfluencers( loadQueryInfluencers );
|
|
||||||
}
|
|
||||||
|
|
||||||
private CollectionLoader generateCollectionLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
|
||||||
if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) {
|
if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) {
|
||||||
final int batchSize = loadQueryInfluencers.effectiveBatchSize( this );
|
final int batchSize = loadQueryInfluencers.effectiveBatchSize( this );
|
||||||
return getFactory().getServiceRegistry()
|
return factory.getServiceRegistry()
|
||||||
.getService( BatchLoaderFactory.class )
|
.getService( BatchLoaderFactory.class )
|
||||||
.createCollectionBatchLoader( batchSize, loadQueryInfluencers, attributeMapping, getFactory() );
|
.createCollectionBatchLoader( batchSize, loadQueryInfluencers, attributeMapping, factory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new CollectionLoaderSingleKey( attributeMapping, loadQueryInfluencers, getFactory() );
|
return new CollectionLoaderSingleKey( attributeMapping, loadQueryInfluencers, factory );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1564,16 +1563,13 @@ public abstract class AbstractCollectionPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers) {
|
public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers) {
|
||||||
if ( affectingFetchProfiles == null ) {
|
if ( affectingFetchProfiles != null && influencers.hasEnabledFetchProfiles() ) {
|
||||||
return false;
|
for ( String profileName : affectingFetchProfiles.keySet() ) {
|
||||||
}
|
if ( influencers.isFetchProfileEnabled( profileName ) ) {
|
||||||
|
return true;
|
||||||
for ( Map.Entry<String, Fetch.Style> entry : affectingFetchProfiles.entrySet() ) {
|
}
|
||||||
if ( influencers.isFetchProfileEnabled( entry.getKey() ) ) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1581,11 +1577,12 @@ public abstract class AbstractCollectionPersister
|
||||||
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers influencers) {
|
||||||
if ( influencers.hasEnabledFilters() ) {
|
if ( influencers.hasEnabledFilters() ) {
|
||||||
final Map<String, Filter> enabledFilters = influencers.getEnabledFilters();
|
final Map<String, Filter> enabledFilters = influencers.getEnabledFilters();
|
||||||
return ( filterHelper != null && filterHelper.isAffectedBy( enabledFilters ) )
|
return filterHelper != null && filterHelper.isAffectedBy( enabledFilters )
|
||||||
|| ( manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters ) );
|
|| manyToManyFilterHelper != null && manyToManyFilterHelper.isAffectedBy( enabledFilters );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.Remove;
|
||||||
import org.hibernate.StaleObjectStateException;
|
import org.hibernate.StaleObjectStateException;
|
||||||
import org.hibernate.StaleStateException;
|
import org.hibernate.StaleStateException;
|
||||||
import org.hibernate.boot.Metadata;
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.boot.spi.SessionFactoryOptions;
|
import org.hibernate.boot.spi.SessionFactoryOptions;
|
||||||
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
|
||||||
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
|
||||||
|
@ -301,6 +302,7 @@ import static org.hibernate.internal.util.collections.ArrayHelper.toTypeArray;
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.setOfSize;
|
import static org.hibernate.internal.util.collections.CollectionHelper.setOfSize;
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallList;
|
import static org.hibernate.internal.util.collections.CollectionHelper.toSmallList;
|
||||||
|
import static org.hibernate.loader.ast.internal.MultiKeyLoadHelper.supportsSqlArrayType;
|
||||||
import static org.hibernate.metamodel.RepresentationMode.POJO;
|
import static org.hibernate.metamodel.RepresentationMode.POJO;
|
||||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
|
import static org.hibernate.persister.entity.DiscriminatorHelper.NOT_NULL_DISCRIMINATOR;
|
||||||
import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR;
|
import static org.hibernate.persister.entity.DiscriminatorHelper.NULL_DISCRIMINATOR;
|
||||||
|
@ -327,8 +329,8 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
private final String sqlAliasStem;
|
private final String sqlAliasStem;
|
||||||
|
|
||||||
private final SingleIdEntityLoader<?> singleIdLoader;
|
private SingleIdEntityLoader<?> singleIdLoader;
|
||||||
private final MultiIdEntityLoader<?> multiIdLoader;
|
private MultiIdEntityLoader<?> multiIdLoader;
|
||||||
private NaturalIdLoader<?> naturalIdLoader;
|
private NaturalIdLoader<?> naturalIdLoader;
|
||||||
private MultiNaturalIdLoader<?> multiNaturalIdLoader;
|
private MultiNaturalIdLoader<?> multiNaturalIdLoader;
|
||||||
|
|
||||||
|
@ -432,6 +434,8 @@ public abstract class AbstractEntityPersister
|
||||||
protected AttributeMappingsMap declaredAttributeMappings = AttributeMappingsMap.builder().build();
|
protected AttributeMappingsMap declaredAttributeMappings = AttributeMappingsMap.builder().build();
|
||||||
protected AttributeMappingsList staticFetchableList;
|
protected AttributeMappingsList staticFetchableList;
|
||||||
|
|
||||||
|
private final String queryLoaderName;
|
||||||
|
|
||||||
private BeforeExecutionGenerator versionGenerator;
|
private BeforeExecutionGenerator versionGenerator;
|
||||||
|
|
||||||
protected ReflectionOptimizer.AccessOptimizer accessOptimizer;
|
protected ReflectionOptimizer.AccessOptimizer accessOptimizer;
|
||||||
|
@ -524,22 +528,7 @@ public abstract class AbstractEntityPersister
|
||||||
final String rowId = persistentClass.getRootTable().getRowId();
|
final String rowId = persistentClass.getRootTable().getRowId();
|
||||||
rowIdName = rowId == null ? null : dialect.rowId( rowId );
|
rowIdName = rowId == null ? null : dialect.rowId( rowId );
|
||||||
|
|
||||||
if ( persistentClass.getLoaderName() != null ) {
|
queryLoaderName = persistentClass.getLoaderName();
|
||||||
// We must resolve the named query on-demand through the boot model because it isn't initialized yet
|
|
||||||
final NamedQueryMemento namedQueryMemento =
|
|
||||||
factory.getQueryEngine().getNamedObjectRepository()
|
|
||||||
.resolve( factory, creationContext.getBootModel(), persistentClass.getLoaderName() );
|
|
||||||
if ( namedQueryMemento == null ) {
|
|
||||||
throw new IllegalArgumentException( "Could not resolve named load-query [" + getEntityName()
|
|
||||||
+ "] : " + persistentClass.getLoaderName() );
|
|
||||||
}
|
|
||||||
singleIdLoader = new SingleIdEntityLoaderProvidedQueryImpl<>( this, namedQueryMemento );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
singleIdLoader = createSingleIdEntityLoader( new LoadQueryInfluencers( factory ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
multiIdLoader = buildMultiIdLoader( persistentClass );
|
|
||||||
|
|
||||||
final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration();
|
final TypeConfiguration typeConfiguration = creationContext.getTypeConfiguration();
|
||||||
final SqmFunctionRegistry functionRegistry = creationContext.getFunctionRegistry();
|
final SqmFunctionRegistry functionRegistry = creationContext.getFunctionRegistry();
|
||||||
|
@ -805,12 +794,29 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
fullDiscriminatorSQLValues = toStringArray( sqlValues );
|
fullDiscriminatorSQLValues = toStringArray( sqlValues );
|
||||||
fullDiscriminatorValues = toObjectArray( values );
|
fullDiscriminatorValues = toObjectArray( values );
|
||||||
|
|
||||||
|
if ( hasNamedQueryLoader() ) {
|
||||||
|
getNamedQueryMemento( creationContext.getBootModel() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NamedQueryMemento getNamedQueryMemento(MetadataImplementor bootModel) {
|
||||||
|
final NamedQueryMemento memento =
|
||||||
|
factory.getQueryEngine().getNamedObjectRepository()
|
||||||
|
.resolve( factory, bootModel, queryLoaderName );
|
||||||
|
if ( memento == null ) {
|
||||||
|
throw new IllegalArgumentException( "Could not resolve named query '" + queryLoaderName
|
||||||
|
+ "' for loading entity '" + getEntityName() + "'" );
|
||||||
|
}
|
||||||
|
return memento;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SingleIdEntityLoader<?> createSingleIdEntityLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
private SingleIdEntityLoader<?> createSingleIdEntityLoader(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) {
|
if ( loadQueryInfluencers.effectivelyBatchLoadable( this ) ) {
|
||||||
final int batchSize = loadQueryInfluencers.effectiveBatchSize( this );
|
final int batchSize = loadQueryInfluencers.effectiveBatchSize( this );
|
||||||
return createBatchingIdEntityLoader( this, batchSize, factory );
|
return factory.getServiceRegistry()
|
||||||
|
.getService( BatchLoaderFactory.class )
|
||||||
|
.createEntityBatchLoader( batchSize, this, factory );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new SingleIdEntityLoaderStandardImpl<>( this, factory );
|
return new SingleIdEntityLoaderStandardImpl<>( this, factory );
|
||||||
|
@ -836,12 +842,14 @@ public abstract class AbstractEntityPersister
|
||||||
return entityNameByTableNameMap;
|
return entityNameByTableNameMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MultiIdEntityLoader<Object> buildMultiIdLoader(PersistentClass persistentClass) {
|
private MultiIdEntityLoader<Object> buildMultiIdLoader() {
|
||||||
if ( persistentClass.getIdentifier() instanceof BasicValue
|
if ( getIdentifierType() instanceof BasicType
|
||||||
&& MultiKeyLoadHelper.supportsSqlArrayType( factory.getServiceRegistry().getService( JdbcServices.class ).getDialect() ) ) {
|
&& supportsSqlArrayType( factory.getJdbcServices().getDialect() ) ) {
|
||||||
return new MultiIdEntityLoaderArrayParam<>( this, factory );
|
return new MultiIdEntityLoaderArrayParam<>( this, factory );
|
||||||
}
|
}
|
||||||
return new MultiIdEntityLoaderStandard<>( this, persistentClass, factory );
|
else {
|
||||||
|
return new MultiIdEntityLoaderStandard<>( this, identifierColumnSpan, factory );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getIdentitySelectString(Dialect dialect) {
|
private String getIdentitySelectString(Dialect dialect) {
|
||||||
|
@ -1051,15 +1059,6 @@ public abstract class AbstractEntityPersister
|
||||||
return tableNames;
|
return tableNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SingleIdEntityLoader<?> createBatchingIdEntityLoader(
|
|
||||||
EntityMappingType entityDescriptor,
|
|
||||||
int domainBatchSize,
|
|
||||||
SessionFactoryImplementor factory) {
|
|
||||||
return factory.getServiceRegistry()
|
|
||||||
.getService( BatchLoaderFactory.class )
|
|
||||||
.createEntityBatchLoader( domainBatchSize, entityDescriptor, factory );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We might need to use cache invalidation if we have formulas,
|
* We might need to use cache invalidation if we have formulas,
|
||||||
* dynamic update, or secondary tables.
|
* dynamic update, or secondary tables.
|
||||||
|
@ -3390,8 +3389,28 @@ public abstract class AbstractEntityPersister
|
||||||
@Override
|
@Override
|
||||||
public final void postInstantiate() throws MappingException {
|
public final void postInstantiate() throws MappingException {
|
||||||
doLateInit();
|
doLateInit();
|
||||||
prepareLoader( singleIdLoader );
|
if ( hasNamedQueryLoader() ) {
|
||||||
|
// 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 ) );
|
||||||
|
}
|
||||||
|
multiIdLoader = buildAndPrepareMultiIdLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiIdEntityLoader<Object> buildAndPrepareMultiIdLoader() {
|
||||||
|
MultiIdEntityLoader<Object> multiIdLoader = buildMultiIdLoader();
|
||||||
prepareLoader( multiIdLoader );
|
prepareLoader( multiIdLoader );
|
||||||
|
return multiIdLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleIdEntityLoader<?> createAndPrepareSingleIdEntityLoader(LoadQueryInfluencers influencers) {
|
||||||
|
SingleIdEntityLoader<?> singleIdLoader = createSingleIdEntityLoader( influencers );
|
||||||
|
prepareLoader( singleIdLoader );
|
||||||
|
return singleIdLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void prepareLoader(Loader loader) {
|
private void prepareLoader(Loader loader) {
|
||||||
|
@ -3430,14 +3449,29 @@ public abstract class AbstractEntityPersister
|
||||||
LOG.tracev( "Fetching entity: {0}", infoString( this, id, getFactory() ) );
|
LOG.tracev( "Fetching entity: {0}", infoString( this, id, getFactory() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( optionalObject == null ) {
|
final SingleIdEntityLoader<?> loader = determineLoaderToUse( session );
|
||||||
return singleIdLoader.load( id, lockOptions, readOnly, session );
|
return optionalObject == null
|
||||||
|
? loader.load( id, lockOptions, readOnly, session )
|
||||||
|
: loader.load( id, optionalObject, lockOptions, readOnly, session );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SingleIdEntityLoader<?> determineLoaderToUse(SharedSessionContractImplementor session) {
|
||||||
|
if ( hasNamedQueryLoader() ) {
|
||||||
|
return getSingleIdLoader();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return singleIdLoader.load( id, optionalObject, lockOptions, readOnly, session );
|
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
|
||||||
|
// no subselect fetching for entities for now
|
||||||
|
return isAffectedByInfluencers( influencers )
|
||||||
|
? createAndPrepareSingleIdEntityLoader( influencers )
|
||||||
|
: getSingleIdLoader();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasNamedQueryLoader() {
|
||||||
|
return queryLoaderName != null;
|
||||||
|
}
|
||||||
|
|
||||||
public SingleIdEntityLoader<?> getSingleIdLoader() {
|
public SingleIdEntityLoader<?> getSingleIdLoader() {
|
||||||
return singleIdLoader;
|
return singleIdLoader;
|
||||||
}
|
}
|
||||||
|
@ -3461,7 +3495,7 @@ public abstract class AbstractEntityPersister
|
||||||
loaded = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( loadEvent, this, entityKey );
|
loaded = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( loadEvent, this, entityKey );
|
||||||
}
|
}
|
||||||
if ( loaded == null ) {
|
if ( loaded == null ) {
|
||||||
loaded = singleIdLoader.load( identifier, entity, LockOptions.NONE, session );
|
loaded = determineLoaderToUse( session ).load( identifier, entity, LockOptions.NONE, session );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( loaded == null ) {
|
if ( loaded == null ) {
|
||||||
|
@ -3517,7 +3551,7 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers loadQueryInfluencers) {
|
public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
if ( affectingFetchProfileNames != null ) {
|
if ( affectingFetchProfileNames != null && loadQueryInfluencers.hasEnabledFetchProfiles() ) {
|
||||||
for ( String profileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
|
for ( String profileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
|
||||||
if ( affectingFetchProfileNames.contains( profileName ) ) {
|
if ( affectingFetchProfileNames.contains( profileName ) ) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -3529,7 +3563,7 @@ public abstract class AbstractEntityPersister
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers loadQueryInfluencers) {
|
public boolean isAffectedByEnabledFilters(LoadQueryInfluencers loadQueryInfluencers) {
|
||||||
if ( loadQueryInfluencers.hasEnabledFilters() && filterHelper != null ) {
|
if ( filterHelper != null && loadQueryInfluencers.hasEnabledFilters() ) {
|
||||||
if ( filterHelper.isAffectedBy( loadQueryInfluencers.getEnabledFilters() ) ) {
|
if ( filterHelper.isAffectedBy( loadQueryInfluencers.getEnabledFilters() ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import java.util.function.Consumer;
|
||||||
import org.hibernate.Incubating;
|
import org.hibernate.Incubating;
|
||||||
import org.hibernate.cache.MutableCacheKeyBuilder;
|
import org.hibernate.cache.MutableCacheKeyBuilder;
|
||||||
import org.hibernate.engine.OptimisticLockStyle;
|
import org.hibernate.engine.OptimisticLockStyle;
|
||||||
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.internal.util.IndexedConsumer;
|
import org.hibernate.internal.util.IndexedConsumer;
|
||||||
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
|
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
|
||||||
|
@ -728,4 +729,19 @@ public class AnonymousTupleEntityValuedModelPart
|
||||||
public boolean containsTableReference(String tableExpression) {
|
public boolean containsTableReference(String tableExpression) {
|
||||||
return ( (TableGroupProducer) delegate ).containsTableReference( tableExpression );
|
return ( (TableGroupProducer) delegate ).containsTableReference( tableExpression );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBatchSize() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNotAffectedByInfluencers(LoadQueryInfluencers influencers) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue