HHH-15879 Introduce a fetchable key for Fetchable within FetchableContainer
This commit is contained in:
parent
69091d1394
commit
37ec41d319
|
@ -56,6 +56,7 @@ import org.hibernate.sql.results.graph.Fetch;
|
|||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
|
||||
|
@ -413,12 +414,12 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
return results.get( 0 );
|
||||
}
|
||||
|
||||
private static List<Fetch> visitFetches(
|
||||
private static ImmutableFetchList visitFetches(
|
||||
FetchParent fetchParent,
|
||||
LoaderSqlAstCreationState creationState) {
|
||||
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
|
||||
final int size = fetchableContainer.getNumberOfFetchables();
|
||||
final List<Fetch> fetches = new ArrayList<>( size );
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchableContainer );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final Fetchable fetchable = fetchableContainer.getFetchable( i );
|
||||
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
|
@ -432,6 +433,6 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
);
|
||||
fetches.add( fetch );
|
||||
}
|
||||
return fetches;
|
||||
return fetches.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.sql.exec.spi.ExecutionContext;
|
|||
import org.hibernate.sql.exec.spi.JdbcOperationQuerySelect;
|
||||
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.internal.RowTransformerDatabaseSnapshotImpl;
|
||||
import org.hibernate.sql.results.spi.ListResultsConsumer;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -76,7 +77,7 @@ class DatabaseSnapshotExecutor {
|
|||
sqlAliasBaseManager,
|
||||
new FromClauseIndex( null ),
|
||||
LockOptions.NONE,
|
||||
(fetchParent, creationState) -> Collections.emptyList(),
|
||||
(fetchParent, creationState) -> ImmutableFetchList.EMPTY,
|
||||
true,
|
||||
sessionFactory
|
||||
);
|
||||
|
|
|
@ -83,6 +83,7 @@ import org.hibernate.sql.results.graph.Fetchable;
|
|||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.collection.internal.CollectionDomainResult;
|
||||
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
|
||||
|
||||
|
@ -648,12 +649,12 @@ public class LoaderSelectBuilder {
|
|||
orderByFragments.add( new AbstractMap.SimpleEntry<>( orderByFragment, tableGroup ) );
|
||||
}
|
||||
|
||||
private List<Fetch> visitFetches(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
|
||||
private ImmutableFetchList visitFetches(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.tracef( "Starting visitation of FetchParent's Fetchables : %s", fetchParent.getNavigablePath() );
|
||||
}
|
||||
|
||||
final List<Fetch> fetches = new ArrayList<>();
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchParent.getReferencedMappingContainer() );
|
||||
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer(
|
||||
fetchParent,
|
||||
creationState,
|
||||
|
@ -671,13 +672,13 @@ public class LoaderSelectBuilder {
|
|||
for ( int i = 0; i < size; i++ ) {
|
||||
processor.accept( referencedMappingContainer.getFetchable( i ), false );
|
||||
}
|
||||
return fetches;
|
||||
return fetches.build();
|
||||
}
|
||||
|
||||
private BiConsumer<Fetchable, Boolean> createFetchableBiConsumer(
|
||||
FetchParent fetchParent,
|
||||
LoaderSqlAstCreationState creationState,
|
||||
List<Fetch> fetches) {
|
||||
ImmutableFetchList.Builder fetches) {
|
||||
return (fetchable, isKeyFetchable) -> {
|
||||
final NavigablePath fetchablePath;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.sql.ast.tree.select.QueryPart;
|
|||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
/**
|
||||
* Helper used when generating the database-snapshot select query
|
||||
|
@ -45,7 +46,7 @@ import org.hibernate.sql.results.graph.FetchParent;
|
|||
public class LoaderSqlAstCreationState
|
||||
implements SqlAstQueryPartProcessingState, SqlAstCreationState, DomainResultCreationState, QueryOptions {
|
||||
public interface FetchProcessor {
|
||||
List<Fetch> visitFetches(FetchParent fetchParent, LoaderSqlAstCreationState creationState);
|
||||
ImmutableFetchList visitFetches(FetchParent fetchParent, LoaderSqlAstCreationState creationState);
|
||||
}
|
||||
|
||||
private final SqlAliasBaseManager sqlAliasBaseManager;
|
||||
|
@ -119,15 +120,15 @@ public class LoaderSqlAstCreationState
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||
public ImmutableFetchList visitFetches(FetchParent fetchParent) {
|
||||
return fetchProcessor.visitFetches( fetchParent, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitNestedFetches(FetchParent fetchParent) {
|
||||
public ImmutableFetchList visitNestedFetches(FetchParent fetchParent) {
|
||||
final FetchParent nestingFetchParent = processingState.getNestingFetchParent();
|
||||
processingState.setNestingFetchParent( fetchParent );
|
||||
final List<Fetch> fetches = fetchProcessor.visitFetches( fetchParent, this );
|
||||
final ImmutableFetchList fetches = fetchProcessor.visitFetches( fetchParent, this );
|
||||
processingState.setNestingFetchParent( nestingFetchParent );
|
||||
return fetches;
|
||||
}
|
||||
|
|
|
@ -14,4 +14,8 @@ import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface BasicEntityIdentifierMapping extends SingleAttributeIdentifierMapping, BasicValuedModelPart {
|
||||
@Override
|
||||
default int getFetchableKey() {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ import org.hibernate.engine.spi.IdentifierValue;
|
|||
*/
|
||||
public interface CompositeIdentifierMapping extends EntityIdentifierMapping, EmbeddableValuedModelPart {
|
||||
|
||||
@Override
|
||||
default int getFetchableKey() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
default IdentifierValue getUnsavedStrategy() {
|
||||
return IdentifierValue.UNDEFINED;
|
||||
|
|
|
@ -42,6 +42,11 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue
|
|||
return getPartName();
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getFetchableKey() {
|
||||
return -2;
|
||||
}
|
||||
|
||||
DiscriminatorType getDiscriminatorType();
|
||||
|
||||
String getConcreteEntityNameForDiscriminatorValue(Object value);
|
||||
|
|
|
@ -45,6 +45,11 @@ public interface NonAggregatedIdentifierMapping extends CompositeIdentifierMappi
|
|||
*/
|
||||
IdentifierValueMapper getIdentifierValueMapper();
|
||||
|
||||
@Override
|
||||
default int getFetchableKey() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Think of an AttributeConverter for id values to account for representation
|
||||
* difference between virtual and id-class mappings
|
||||
|
|
|
@ -99,6 +99,11 @@ public interface PluralAttributeMapping
|
|||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
default int getNumberOfFetchableKeys() {
|
||||
return getNumberOfKeyFetchables() + getNumberOfFetchables();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void visitFetchables(IndexedConsumer<? super Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
|
||||
fetchableConsumer.accept( 0, getElementDescriptor() );
|
||||
|
|
|
@ -17,11 +17,13 @@ import org.hibernate.type.descriptor.java.JavaType;
|
|||
*/
|
||||
public abstract class AbstractAttributeMapping implements AttributeMapping {
|
||||
private final String name;
|
||||
private final int fetchableIndex;
|
||||
|
||||
private final ManagedMappingType declaringType;
|
||||
|
||||
public AbstractAttributeMapping(String name, ManagedMappingType declaringType) {
|
||||
public AbstractAttributeMapping(String name, int fetchableIndex, ManagedMappingType declaringType) {
|
||||
this.name = name;
|
||||
this.fetchableIndex = fetchableIndex;
|
||||
this.declaringType = declaringType;
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,11 @@ public abstract class AbstractAttributeMapping implements AttributeMapping {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return fetchableIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return getMappedType();
|
||||
|
|
|
@ -300,6 +300,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
declarer,
|
||||
(BasicType<?>) subtype,
|
||||
|
@ -380,6 +381,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
typeConfiguration.getJavaTypeRegistry().getDescriptor( Object.class ),
|
||||
declarer,
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
attributeMetadataAccess,
|
||||
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
|
@ -407,6 +409,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
declarer,
|
||||
subCompositeType,
|
||||
|
@ -426,6 +429,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
propertyAccess,
|
||||
|
@ -442,6 +446,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
|
|||
bootPropertyDescriptor.getName(),
|
||||
navigableRole.append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
|
|
|
@ -114,6 +114,11 @@ public abstract class AbstractEntityCollectionPart implements EntityCollectionPa
|
|||
return nature.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return nature == Nature.INDEX || !collectionDescriptor.hasIndex() ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getAssociatedEntityMappingType() {
|
||||
return associatedEntityTypeDescriptor;
|
||||
|
|
|
@ -27,23 +27,25 @@ public abstract class AbstractSingularAttributeMapping
|
|||
public AbstractSingularAttributeMapping(
|
||||
String name,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchOptions mappedFetchOptions,
|
||||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess) {
|
||||
super( name, attributeMetadata, mappedFetchOptions, stateArrayPosition, declaringType );
|
||||
super( name, attributeMetadata, mappedFetchOptions, stateArrayPosition, fetchableIndex, declaringType );
|
||||
this.propertyAccess = propertyAccess;
|
||||
}
|
||||
|
||||
public AbstractSingularAttributeMapping(
|
||||
String name,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchTiming fetchTiming,
|
||||
FetchStyle fetchStyle,
|
||||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess) {
|
||||
super( name, attributeMetadata, fetchTiming, fetchStyle, stateArrayPosition, declaringType );
|
||||
super( name, attributeMetadata, fetchTiming, fetchStyle, stateArrayPosition, fetchableIndex, declaringType );
|
||||
this.propertyAccess = propertyAccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,8 +30,9 @@ public abstract class AbstractStateArrayContributorMapping
|
|||
FetchTiming fetchTiming,
|
||||
FetchStyle fetchStyle,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
ManagedMappingType declaringType) {
|
||||
super( name, declaringType );
|
||||
super( name, fetchableIndex, declaringType );
|
||||
this.attributeMetadata = attributeMetadata;
|
||||
this.fetchTiming = fetchTiming;
|
||||
this.fetchStyle = fetchStyle;
|
||||
|
@ -43,6 +44,7 @@ public abstract class AbstractStateArrayContributorMapping
|
|||
AttributeMetadata attributeMetadata,
|
||||
FetchOptions mappedFetchOptions,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
ManagedMappingType declaringType) {
|
||||
this(
|
||||
name,
|
||||
|
@ -50,6 +52,7 @@ public abstract class AbstractStateArrayContributorMapping
|
|||
mappedFetchOptions.getTiming(),
|
||||
mappedFetchOptions.getStyle(),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
declaringType
|
||||
);
|
||||
}
|
||||
|
|
|
@ -59,8 +59,8 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
|
|||
private final Integer precision;
|
||||
private final Integer scale;
|
||||
|
||||
private boolean isInsertable;
|
||||
private boolean isUpdateable;
|
||||
private final boolean insertable;
|
||||
private final boolean updateable;
|
||||
private final MetaType metaType;
|
||||
|
||||
public AnyDiscriminatorPart(
|
||||
|
@ -83,8 +83,8 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
|
|||
this.length = length;
|
||||
this.precision = precision;
|
||||
this.scale = scale;
|
||||
this.isInsertable = insertable;
|
||||
this.isUpdateable = updateable;
|
||||
this.insertable = insertable;
|
||||
this.updateable = updateable;
|
||||
this.metaType = metaType;
|
||||
}
|
||||
|
||||
|
@ -118,12 +118,12 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
|
|||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return isInsertable;
|
||||
return insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdateable() {
|
||||
return isUpdateable;
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -235,6 +235,11 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
|
|||
return getPartName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -54,8 +54,8 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
private final Integer precision;
|
||||
private final Integer scale;
|
||||
private final boolean nullable;
|
||||
private boolean isInsertable;
|
||||
private boolean isUpdateable;
|
||||
private final boolean insertable;
|
||||
private final boolean updateable;
|
||||
private final JdbcMapping jdbcMapping;
|
||||
|
||||
public AnyKeyPart(
|
||||
|
@ -80,8 +80,8 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
this.precision = precision;
|
||||
this.scale = scale;
|
||||
this.nullable = nullable;
|
||||
this.isInsertable = insertable;
|
||||
this.isUpdateable = updateable;
|
||||
this.insertable = insertable;
|
||||
this.updateable = updateable;
|
||||
this.jdbcMapping = jdbcMapping;
|
||||
}
|
||||
|
||||
|
@ -107,12 +107,12 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
|
||||
@Override
|
||||
public boolean isInsertable() {
|
||||
return isInsertable;
|
||||
return insertable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdateable() {
|
||||
return isUpdateable;
|
||||
return updateable;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -180,6 +180,11 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
return getPartName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -69,6 +69,7 @@ public class BasicAttributeMapping
|
|||
String attributeName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchTiming mappedFetchTiming,
|
||||
FetchStyle mappedFetchStyle,
|
||||
|
@ -91,6 +92,7 @@ public class BasicAttributeMapping
|
|||
super(
|
||||
attributeName,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadata,
|
||||
mappedFetchTiming,
|
||||
mappedFetchStyle,
|
||||
|
@ -155,6 +157,7 @@ public class BasicAttributeMapping
|
|||
attributeName,
|
||||
original.getNavigableRole(),
|
||||
stateArrayPosition,
|
||||
original.getFetchableKey(),
|
||||
attributeMetadata,
|
||||
FetchTiming.IMMEDIATE,
|
||||
FetchStyle.JOIN,
|
||||
|
|
|
@ -232,6 +232,11 @@ public class BasicValuedCollectionPart
|
|||
return nature.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return nature == Nature.INDEX || !collectionDescriptor.hasIndex() ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -206,6 +206,11 @@ public class CollectionIdentifierDescriptorImpl implements CollectionIdentifierD
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping.internal;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
@ -19,7 +18,6 @@ import org.hibernate.NotYetImplementedFor6Exception;
|
|||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.loader.ast.internal.CompoundNaturalIdLoader;
|
||||
import org.hibernate.loader.ast.internal.MultiNaturalIdLoaderStandard;
|
||||
import org.hibernate.loader.ast.spi.MultiNaturalIdLoader;
|
||||
|
@ -48,6 +46,7 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
@ -453,7 +452,9 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
private final CompoundNaturalIdMapping naturalIdMapping;
|
||||
private final JavaType<Object[]> arrayJtd;
|
||||
|
||||
private final List<Fetch> fetches;
|
||||
private final ImmutableFetchList fetches;
|
||||
private final boolean hasJoinFetches;
|
||||
private final boolean containsCollectionFetches;
|
||||
|
||||
private final String resultVariable;
|
||||
|
||||
|
@ -468,7 +469,9 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
this.arrayJtd = arrayJtd;
|
||||
this.resultVariable = resultVariable;
|
||||
|
||||
this.fetches = Collections.unmodifiableList( creationState.visitFetches( this ) );
|
||||
this.fetches = creationState.visitFetches( this );
|
||||
this.hasJoinFetches = this.fetches.hasJoinFetches();
|
||||
this.containsCollectionFetches = this.fetches.containsCollectionFetches();
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -517,22 +520,24 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
public ImmutableFetchList getFetches() {
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch findFetch(Fetchable fetchable) {
|
||||
assert fetchable != null;
|
||||
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
if ( fetchable.equals( fetch.getFetchedMapping() ) ) {
|
||||
return fetch;
|
||||
}
|
||||
return fetches.get( fetchable );
|
||||
}
|
||||
|
||||
return null;
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return hasJoinFetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return containsCollectionFetches;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,10 +546,10 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
private final CompoundNaturalIdMapping naturalIdMapping;
|
||||
private final JavaType<Object[]> jtd;
|
||||
|
||||
private final List<DomainResultAssembler<?>> subAssemblers;
|
||||
private final DomainResultAssembler<?>[] subAssemblers;
|
||||
|
||||
private AssemblerImpl(
|
||||
List<Fetch> fetches,
|
||||
ImmutableFetchList fetches,
|
||||
NavigablePath navigablePath,
|
||||
CompoundNaturalIdMapping naturalIdMapping,
|
||||
JavaType<Object[]> jtd,
|
||||
|
@ -557,11 +562,10 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
// we just "need it" as an impl detail for handling Fetches
|
||||
final InitializerImpl initializer = new InitializerImpl( navigablePath, naturalIdMapping );
|
||||
|
||||
this.subAssemblers = CollectionHelper.arrayList( fetches.size() );
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
final DomainResultAssembler<?> fetchAssembler = fetch.createAssembler( initializer, creationState );
|
||||
subAssemblers.add( fetchAssembler );
|
||||
this.subAssemblers = new DomainResultAssembler[fetches.size()];
|
||||
int i = 0;
|
||||
for ( Fetch fetch : fetches ) {
|
||||
subAssemblers[i++] = fetch.createAssembler( initializer, creationState );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -569,9 +573,9 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
|
|||
public Object[] assemble(
|
||||
RowProcessingState rowProcessingState,
|
||||
JdbcValuesSourceProcessingOptions options) {
|
||||
final Object[] result = new Object[ subAssemblers.size() ];
|
||||
for ( int i = 0; i < subAssemblers.size(); i++ ) {
|
||||
result[ i ] = subAssemblers.get( i ).assemble( rowProcessingState, options );
|
||||
final Object[] result = new Object[ subAssemblers.length ];
|
||||
for ( int i = 0; i < subAssemblers.length; i++ ) {
|
||||
result[ i ] = subAssemblers[i].assemble( rowProcessingState, options );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ public class DiscriminatedAssociationAttributeMapping
|
|||
JavaType<?> baseAssociationJtd,
|
||||
ManagedMappingType declaringType,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchTiming fetchTiming,
|
||||
PropertyAccess propertyAccess,
|
||||
|
@ -81,6 +82,7 @@ public class DiscriminatedAssociationAttributeMapping
|
|||
super(
|
||||
bootProperty.getName(),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadata,
|
||||
fetchTiming,
|
||||
FetchStyle.SELECT,
|
||||
|
@ -188,8 +190,10 @@ public class DiscriminatedAssociationAttributeMapping
|
|||
public Fetchable getFetchable(int position) {
|
||||
switch ( position ) {
|
||||
case 0:
|
||||
assert getDiscriminatorPart().getFetchableKey() == 0;
|
||||
return getDiscriminatorPart();
|
||||
case 1:
|
||||
assert getKeyPart().getFetchableKey() == 1;
|
||||
return getKeyPart();
|
||||
}
|
||||
throw new IndexOutOfBoundsException(position);
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.sql.results.graph.FetchOptions;
|
|||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
import org.hibernate.type.AnyType;
|
||||
|
@ -413,7 +414,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
|||
|
||||
private Fetch discriminatorValueFetch;
|
||||
private Fetch keyValueFetch;
|
||||
private List<Fetch> fetches;
|
||||
private ImmutableFetchList fetches;
|
||||
|
||||
public AnyValuedResultGraphNode(
|
||||
NavigablePath navigablePath,
|
||||
|
@ -425,11 +426,11 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
|||
}
|
||||
|
||||
protected void afterInitialize(DomainResultCreationState creationState) {
|
||||
this.fetches = Collections.unmodifiableList( creationState.visitFetches( this ) );
|
||||
this.fetches = creationState.visitFetches( this );
|
||||
assert fetches.size() == 2;
|
||||
|
||||
discriminatorValueFetch = fetches.get( 0 );
|
||||
keyValueFetch = fetches.get( 1 );
|
||||
discriminatorValueFetch = fetches.get( graphedPart.getDiscriminatorPart() );
|
||||
keyValueFetch = fetches.get( graphedPart.getKeyPart() );
|
||||
}
|
||||
|
||||
public Fetch getDiscriminatorValueFetch() {
|
||||
|
@ -470,7 +471,7 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
public ImmutableFetchList getFetches() {
|
||||
return fetches;
|
||||
}
|
||||
|
||||
|
@ -486,6 +487,16 @@ public class DiscriminatedAssociationMapping implements MappingType, FetchOption
|
|||
|
||||
throw new IllegalArgumentException( "Given Fetchable [" + fetchable + "] did not match either discriminator nor key mapping" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnyValuedResult<T> extends AnyValuedResultGraphNode implements DomainResult<T> {
|
||||
|
|
|
@ -117,6 +117,11 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
|
|||
return nature.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return nature == Nature.INDEX || !collectionDescriptor.hasIndex() ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return discriminatorMapping;
|
||||
|
|
|
@ -407,6 +407,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
bootPropertyDescriptor.getName(),
|
||||
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
(BasicType<?>) subtype,
|
||||
|
@ -488,6 +489,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
typeConfiguration.getJavaTypeRegistry().getDescriptor( Object.class ),
|
||||
this,
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
attributeMetadataAccess,
|
||||
bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
|
@ -515,6 +517,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
this,
|
||||
subCompositeType,
|
||||
|
@ -533,6 +536,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
bootPropertyDescriptor.getName(),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
representationStrategy.resolvePropertyAccess( bootPropertyDescriptor ),
|
||||
|
@ -548,6 +552,7 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
|
|||
bootPropertyDescriptor.getName(),
|
||||
valueMapping.getNavigableRole().append( bootPropertyDescriptor.getName() ),
|
||||
attributeIndex,
|
||||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
|
|
|
@ -75,6 +75,7 @@ public class EmbeddedAttributeMapping
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
String tableExpression,
|
||||
AttributeMetadata attributeMetadata,
|
||||
String parentInjectionAttributeName,
|
||||
|
@ -87,6 +88,7 @@ public class EmbeddedAttributeMapping
|
|||
name,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
tableExpression,
|
||||
attributeMetadata,
|
||||
getPropertyAccess( parentInjectionAttributeName, embeddableMappingType ),
|
||||
|
@ -102,6 +104,7 @@ public class EmbeddedAttributeMapping
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
String tableExpression,
|
||||
AttributeMetadata attributeMetadata,
|
||||
PropertyAccess parentInjectionAttributePropertyAccess,
|
||||
|
@ -113,6 +116,7 @@ public class EmbeddedAttributeMapping
|
|||
super(
|
||||
name,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadata,
|
||||
mappedFetchTiming,
|
||||
mappedFetchStyle,
|
||||
|
@ -139,6 +143,7 @@ public class EmbeddedAttributeMapping
|
|||
super(
|
||||
inverseModelPart.getFetchableName(),
|
||||
-1,
|
||||
inverseModelPart.getFetchableKey(),
|
||||
null,
|
||||
inverseModelPart.getMappedFetchOptions(),
|
||||
keyDeclaringType,
|
||||
|
|
|
@ -140,6 +140,11 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
return getNature().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return nature == Nature.INDEX || !collectionDescriptor.hasIndex() ? 0 : 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -207,6 +207,11 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
|
|||
return attributeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return getVersionAttribute().getFetchableKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -107,6 +107,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
|
|||
.append( EntityIdentifierMapping.ROLE_LOCAL_NAME )
|
||||
.append( NavigablePath.IDENTIFIER_MAPPER_PROPERTY ),
|
||||
-1,
|
||||
-1,
|
||||
idTable,
|
||||
attributeMetadata,
|
||||
(PropertyAccess) null,
|
||||
|
|
|
@ -178,6 +178,7 @@ public class MappingModelCreationHelper {
|
|||
String attrName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
BasicType attrType,
|
||||
|
@ -223,6 +224,7 @@ public class MappingModelCreationHelper {
|
|||
attrName,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadata,
|
||||
fetchTiming,
|
||||
fetchStyle,
|
||||
|
@ -249,6 +251,7 @@ public class MappingModelCreationHelper {
|
|||
public static EmbeddedAttributeMapping buildEmbeddedAttributeMapping(
|
||||
String attrName,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
CompositeType attrType,
|
||||
|
@ -280,6 +283,7 @@ public class MappingModelCreationHelper {
|
|||
attrName,
|
||||
declaringType.getNavigableRole().append( attrName ),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
tableExpression,
|
||||
attributeMetadataAccess,
|
||||
component.getParentProperty(),
|
||||
|
@ -295,6 +299,7 @@ public class MappingModelCreationHelper {
|
|||
attrName,
|
||||
declaringType.getNavigableRole().append( attrName ),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
tableExpression,
|
||||
attributeMetadataAccess,
|
||||
component.getParentProperty(),
|
||||
|
@ -373,6 +378,7 @@ public class MappingModelCreationHelper {
|
|||
public static PluralAttributeMapping buildPluralAttributeMapping(
|
||||
String attrName,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
PropertyAccess propertyAccess,
|
||||
|
@ -578,6 +584,7 @@ public class MappingModelCreationHelper {
|
|||
attributeMetadata,
|
||||
collectionMappingType,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
elementDescriptor,
|
||||
indexDescriptor,
|
||||
identifierDescriptor,
|
||||
|
@ -1492,6 +1499,7 @@ public class MappingModelCreationHelper {
|
|||
String attrName,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
EntityPersister declaringEntityPersister,
|
||||
|
@ -1546,6 +1554,7 @@ public class MappingModelCreationHelper {
|
|||
attrName,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
(ToOne) bootProperty.getValue(),
|
||||
attributeMetadata,
|
||||
fetchTiming,
|
||||
|
|
|
@ -119,6 +119,7 @@ public class PluralAttributeMappingImpl
|
|||
AttributeMetadata attributeMetadata,
|
||||
CollectionMappingType<?> collectionMappingType,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
CollectionPart elementDescriptor,
|
||||
CollectionPart indexDescriptor,
|
||||
CollectionIdentifierDescriptor identifierDescriptor,
|
||||
|
@ -127,7 +128,7 @@ public class PluralAttributeMappingImpl
|
|||
CascadeStyle cascadeStyle,
|
||||
ManagedMappingType declaringType,
|
||||
CollectionPersister collectionDescriptor) {
|
||||
super( attributeName, declaringType );
|
||||
super( attributeName, fetchableIndex, declaringType );
|
||||
this.propertyAccess = propertyAccess;
|
||||
this.attributeMetadata = attributeMetadata;
|
||||
this.collectionMappingType = collectionMappingType;
|
||||
|
|
|
@ -581,6 +581,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
return PART_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return this;
|
||||
|
|
|
@ -160,6 +160,7 @@ public class ToOneAttributeMapping
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
ToOne bootValue,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchOptions mappedFetchOptions,
|
||||
|
@ -171,6 +172,7 @@ public class ToOneAttributeMapping
|
|||
name,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootValue,
|
||||
attributeMetadata,
|
||||
mappedFetchOptions.getTiming(),
|
||||
|
@ -186,6 +188,7 @@ public class ToOneAttributeMapping
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
ToOne bootValue,
|
||||
AttributeMetadata attributeMetadata,
|
||||
FetchTiming mappedFetchTiming,
|
||||
|
@ -197,6 +200,7 @@ public class ToOneAttributeMapping
|
|||
super(
|
||||
name,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadata,
|
||||
adjustFetchTiming( mappedFetchTiming, bootValue ),
|
||||
mappedFetchStyle,
|
||||
|
@ -548,6 +552,7 @@ public class ToOneAttributeMapping
|
|||
super(
|
||||
original.getAttributeName(),
|
||||
original.getStateArrayPosition(),
|
||||
original.getFetchableKey(),
|
||||
original.getAttributeMetadata(),
|
||||
original,
|
||||
declaringType,
|
||||
|
|
|
@ -27,6 +27,7 @@ public class VirtualEmbeddedAttributeMapping extends EmbeddedAttributeMapping im
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
String tableExpression,
|
||||
AttributeMetadata attributeMetadata,
|
||||
String parentInjectionAttributeName,
|
||||
|
@ -39,6 +40,7 @@ public class VirtualEmbeddedAttributeMapping extends EmbeddedAttributeMapping im
|
|||
name,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
tableExpression,
|
||||
attributeMetadata,
|
||||
parentInjectionAttributeName,
|
||||
|
@ -54,6 +56,7 @@ public class VirtualEmbeddedAttributeMapping extends EmbeddedAttributeMapping im
|
|||
String name,
|
||||
NavigableRole navigableRole,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
String tableExpression,
|
||||
AttributeMetadata attributeMetadata,
|
||||
PropertyAccess parentInjectionAttributePropertyAccess,
|
||||
|
@ -66,6 +69,7 @@ public class VirtualEmbeddedAttributeMapping extends EmbeddedAttributeMapping im
|
|||
name,
|
||||
navigableRole,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
tableExpression,
|
||||
attributeMetadata,
|
||||
parentInjectionAttributePropertyAccess,
|
||||
|
|
|
@ -125,6 +125,7 @@ import org.hibernate.sql.model.internal.TableDeleteStandard;
|
|||
import org.hibernate.sql.model.jdbc.JdbcDeleteMutation;
|
||||
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.internal.SqlSelectionImpl;
|
||||
import org.hibernate.generator.Generator;
|
||||
import org.hibernate.generator.InMemoryGenerator;
|
||||
|
@ -934,7 +935,7 @@ public abstract class AbstractCollectionPersister
|
|||
new SqlAliasBaseManager(),
|
||||
new SimpleFromClauseAccessImpl(),
|
||||
LockOptions.NONE,
|
||||
(fetchParent, creationState) -> new ArrayList<>(),
|
||||
(fetchParent, creationState) -> ImmutableFetchList.EMPTY,
|
||||
true,
|
||||
getFactory()
|
||||
);
|
||||
|
|
|
@ -261,6 +261,7 @@ import org.hibernate.sql.results.graph.Fetchable;
|
|||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||
import org.hibernate.tuple.NonIdentifierAttribute;
|
||||
|
@ -1797,10 +1798,10 @@ public abstract class AbstractEntityPersister
|
|||
return expression;
|
||||
}
|
||||
|
||||
private List<Fetch> fetchProcessor(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
|
||||
private ImmutableFetchList fetchProcessor(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
|
||||
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
|
||||
final int size = fetchableContainer.getNumberOfFetchables();
|
||||
final List<Fetch> fetches = new ArrayList<>( size );
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchableContainer );
|
||||
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final Fetchable fetchable = fetchableContainer.getFetchable( i );
|
||||
|
@ -1848,7 +1849,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
|
||||
return fetches;
|
||||
return fetches.build();
|
||||
}
|
||||
|
||||
private boolean isSelectable(FetchParent fetchParent, Fetchable fetchable) {
|
||||
|
@ -4652,6 +4653,7 @@ public abstract class AbstractEntityPersister
|
|||
|
||||
final NonIdentifierAttribute[] properties = currentEntityMetamodel.getProperties();
|
||||
AttributeMappingsMap.Builder mappingsBuilder = AttributeMappingsMap.builder();
|
||||
int fetchableIndex = getFetchableIndexOffset();
|
||||
for ( int i = 0; i < currentEntityMetamodel.getPropertySpan(); i++ ) {
|
||||
final NonIdentifierAttribute runtimeAttrDefinition = properties[i];
|
||||
final Property bootProperty = bootEntityDescriptor.getProperty( runtimeAttrDefinition.getName() );
|
||||
|
@ -4664,6 +4666,7 @@ public abstract class AbstractEntityPersister
|
|||
runtimeAttrDefinition,
|
||||
bootProperty,
|
||||
stateArrayPosition++,
|
||||
fetchableIndex++,
|
||||
creationProcess
|
||||
)
|
||||
);
|
||||
|
@ -4701,6 +4704,7 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
final ImmutableAttributeMappingList.Builder builder = new ImmutableAttributeMappingList.Builder( attributeMappings.size() );
|
||||
visitSubTypeAttributeMappings( attributeMapping -> builder.add( attributeMapping ) );
|
||||
assert superMappingType != null || builder.assertFetchableIndexes();
|
||||
staticFetchableList = builder.build();
|
||||
return true;
|
||||
}
|
||||
|
@ -4767,6 +4771,30 @@ public abstract class AbstractEntityPersister
|
|||
}
|
||||
}
|
||||
|
||||
private int getFetchableIndexOffset() {
|
||||
if ( superMappingType != null ) {
|
||||
final EntityMappingType rootEntityDescriptor = getRootEntityDescriptor();
|
||||
int offset = rootEntityDescriptor.getNumberOfDeclaredAttributeMappings();
|
||||
for ( EntityMappingType subMappingType : rootEntityDescriptor.getSubMappingTypes() ) {
|
||||
if ( subMappingType == this ) {
|
||||
break;
|
||||
}
|
||||
// Determining the number of attribute mappings unfortunately has to be done this way,
|
||||
// because calling `subMappingType.getNumberOfDeclaredAttributeMappings()` at this point
|
||||
// may produce wrong results because subMappingType might not have completed prepareMappingModel yet
|
||||
final int propertySpan = subMappingType.getEntityPersister().getEntityMetamodel().getPropertySpan();
|
||||
final int superPropertySpan = subMappingType.getSuperMappingType()
|
||||
.getEntityPersister()
|
||||
.getEntityMetamodel()
|
||||
.getPropertySpan();
|
||||
final int numberOfDeclaredAttributeMappings = propertySpan - superPropertySpan;
|
||||
offset += numberOfDeclaredAttributeMappings;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void prepareMappingModel(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) {
|
||||
final EntityInstantiator instantiator = getRepresentationStrategy().getInstantiator();
|
||||
final Supplier<?> templateInstanceCreator;
|
||||
|
@ -5206,6 +5234,7 @@ public abstract class AbstractEntityPersister
|
|||
NonIdentifierAttribute tupleAttrDefinition,
|
||||
Property bootProperty,
|
||||
int stateArrayPosition,
|
||||
int fetchableIndex,
|
||||
MappingModelCreationProcess creationProcess) {
|
||||
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
|
||||
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
|
||||
|
@ -5229,6 +5258,7 @@ public abstract class AbstractEntityPersister
|
|||
attrName,
|
||||
getNavigableRole().append( bootProperty.getName() ),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
(BasicType<?>) attrType,
|
||||
|
@ -5318,6 +5348,7 @@ public abstract class AbstractEntityPersister
|
|||
attrName,
|
||||
getNavigableRole().append( bootProperty.getName() ),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
(BasicType<?>) attrType,
|
||||
|
@ -5362,6 +5393,7 @@ public abstract class AbstractEntityPersister
|
|||
baseAssociationJtd,
|
||||
this,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
attributeMetadataAccess,
|
||||
bootProperty.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE,
|
||||
propertyAccess,
|
||||
|
@ -5375,6 +5407,7 @@ public abstract class AbstractEntityPersister
|
|||
return MappingModelCreationHelper.buildEmbeddedAttributeMapping(
|
||||
attrName,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
(CompositeType) attrType,
|
||||
|
@ -5389,6 +5422,7 @@ public abstract class AbstractEntityPersister
|
|||
return MappingModelCreationHelper.buildPluralAttributeMapping(
|
||||
attrName,
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
propertyAccess,
|
||||
|
@ -5402,6 +5436,7 @@ public abstract class AbstractEntityPersister
|
|||
attrName,
|
||||
getNavigableRole().append( attrName ),
|
||||
stateArrayPosition,
|
||||
fetchableIndex,
|
||||
bootProperty,
|
||||
this,
|
||||
this,
|
||||
|
@ -5659,6 +5694,11 @@ public abstract class AbstractEntityPersister
|
|||
return getStaticFetchableList().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfFetchableKeys() {
|
||||
return superMappingType == null ? getNumberOfFetchables() : getRootEntityDescriptor().getNumberOfFetchables();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfKeyFetchables() {
|
||||
return 0;
|
||||
|
|
|
@ -90,6 +90,13 @@ public final class ImmutableAttributeMappingList implements AttributeMappingsLis
|
|||
return new ImmutableAttributeMappingList( builderList );
|
||||
}
|
||||
|
||||
public boolean assertFetchableIndexes() {
|
||||
for ( int i = 0; i < builderList.size(); i++ ) {
|
||||
final AttributeMapping attributeMapping = builderList.get( i );
|
||||
assert i == attributeMapping.getFetchableKey();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public class AnonymousTupleBasicEntityIdentifierMapping
|
|||
SqmExpressible<?> expressible,
|
||||
JdbcMapping jdbcMapping,
|
||||
BasicEntityIdentifierMapping delegate) {
|
||||
super( delegate.getAttributeName(), selectionExpression, expressible, jdbcMapping );
|
||||
super( delegate.getAttributeName(), selectionExpression, expressible, jdbcMapping, -1 );
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,16 +47,19 @@ public class AnonymousTupleBasicValuedModelPart implements ModelPart, MappingTyp
|
|||
private final String selectionExpression;
|
||||
private final SqmExpressible<?> expressible;
|
||||
private final JdbcMapping jdbcMapping;
|
||||
private final int fetchableIndex;
|
||||
|
||||
public AnonymousTupleBasicValuedModelPart(
|
||||
String partName,
|
||||
String selectionExpression,
|
||||
SqmExpressible<?> expressible,
|
||||
JdbcMapping jdbcMapping) {
|
||||
JdbcMapping jdbcMapping,
|
||||
int fetchableIndex) {
|
||||
this.partName = partName;
|
||||
this.selectionExpression = selectionExpression;
|
||||
this.expressible = expressible;
|
||||
this.jdbcMapping = jdbcMapping;
|
||||
this.fetchableIndex = fetchableIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -164,6 +167,11 @@ public class AnonymousTupleBasicValuedModelPart implements ModelPart, MappingTyp
|
|||
return partName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return fetchableIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return FETCH_OPTIONS;
|
||||
|
|
|
@ -73,16 +73,19 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
|
|||
private final DomainType<?> domainType;
|
||||
private final String componentName;
|
||||
private final EmbeddableValuedModelPart existingModelPartContainer;
|
||||
private final int fetchableIndex;
|
||||
|
||||
public AnonymousTupleEmbeddableValuedModelPart(
|
||||
Map<String, ModelPart> modelParts,
|
||||
DomainType<?> domainType,
|
||||
String componentName,
|
||||
EmbeddableValuedModelPart existingModelPartContainer) {
|
||||
EmbeddableValuedModelPart existingModelPartContainer,
|
||||
int fetchableIndex) {
|
||||
this.modelParts = modelParts;
|
||||
this.domainType = domainType;
|
||||
this.componentName = componentName;
|
||||
this.existingModelPartContainer = existingModelPartContainer;
|
||||
this.fetchableIndex = fetchableIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -321,6 +324,11 @@ public class AnonymousTupleEmbeddableValuedModelPart implements EmbeddableValued
|
|||
return getPartName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFetchableKey() {
|
||||
return fetchableIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchOptions getMappedFetchOptions() {
|
||||
return FETCH_OPTIONS;
|
||||
|
|
|
@ -37,7 +37,8 @@ public class AnonymousTupleEmbeddedEntityIdentifierMapping extends AnonymousTupl
|
|||
modelParts,
|
||||
domainType,
|
||||
componentName,
|
||||
(EmbeddableValuedModelPart) delegate
|
||||
(EmbeddableValuedModelPart) delegate,
|
||||
-1
|
||||
);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
|
|
@ -82,12 +82,14 @@ public class AnonymousTupleEntityValuedModelPart
|
|||
private final String componentName;
|
||||
private final EntityValuedModelPart delegate;
|
||||
private final Set<String> targetKeyPropertyNames;
|
||||
private final int fetchableIndex;
|
||||
|
||||
public AnonymousTupleEntityValuedModelPart(
|
||||
EntityIdentifierMapping identifierMapping,
|
||||
DomainType<?> domainType,
|
||||
String componentName,
|
||||
EntityValuedModelPart delegate) {
|
||||
EntityValuedModelPart delegate,
|
||||
int fetchableIndex) {
|
||||
this.identifierMapping = identifierMapping;
|
||||
this.domainType = domainType;
|
||||
this.componentName = componentName;
|
||||
|
@ -103,6 +105,7 @@ public class AnonymousTupleEntityValuedModelPart
|
|||
persister.getFactory()
|
||||
);
|
||||
this.targetKeyPropertyNames = targetKeyPropertyNames;
|
||||
this.fetchableIndex = fetchableIndex;
|
||||
}
|
||||
|
||||
public ModelPart getForeignKeyPart() {
|
||||
|
|
|
@ -38,7 +38,8 @@ public class AnonymousTupleNonAggregatedEntityIdentifierMapping extends Anonymou
|
|||
modelParts,
|
||||
domainType,
|
||||
componentName,
|
||||
delegate
|
||||
delegate,
|
||||
-1
|
||||
);
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
partName,
|
||||
partName,
|
||||
tableGroup == null ? null : getModelPart( tableGroup ),
|
||||
compatibleTableExpressions
|
||||
compatibleTableExpressions,
|
||||
modelParts.size()
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
@ -108,7 +109,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
selectableNode.getExpressible(),
|
||||
sqlSelection.getExpressionType()
|
||||
.getJdbcMappings()
|
||||
.get( 0 )
|
||||
.get( 0 ),
|
||||
modelParts.size()
|
||||
);
|
||||
}
|
||||
modelParts.put( partName, modelPart );
|
||||
|
@ -136,7 +138,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
String selectionExpression,
|
||||
String partName,
|
||||
ModelPart existingModelPart,
|
||||
Set<String> compatibleTableExpressions) {
|
||||
Set<String> compatibleTableExpressions,
|
||||
int fetchableIndex) {
|
||||
if ( domainType instanceof EntityDomainType<?> ) {
|
||||
final EntityValuedModelPart existingModelPartContainer = (EntityValuedModelPart) existingModelPart;
|
||||
final EntityIdentifierMapping identifierMapping = existingModelPartContainer.getEntityMappingType()
|
||||
|
@ -149,6 +152,7 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
final Set<Attribute<?, ?>> attributes = (Set<Attribute<?, ?>>) ( (ManagedDomainType<?>) ( (EntityDomainType<?>) domainType ).getIdentifierDescriptor().getSqmPathType() ).getAttributes();
|
||||
final Map<String, ModelPart> modelParts = CollectionHelper.linkedMapOfSize( attributes.size() );
|
||||
final EmbeddableValuedModelPart modelPartContainer = (EmbeddableValuedModelPart) identifierMapping;
|
||||
int index = 0;
|
||||
for ( Attribute<?, ?> attribute : attributes ) {
|
||||
if ( !( attribute instanceof SingularPersistentAttribute<?, ?> ) ) {
|
||||
throw new IllegalArgumentException( "Only embeddables without collections are supported!" );
|
||||
|
@ -162,7 +166,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
selectionExpression + "_" + attributeName + "_" + attribute.getName(),
|
||||
attribute.getName(),
|
||||
modelPartContainer.findSubPart( attribute.getName(), null ),
|
||||
compatibleTableExpressions
|
||||
compatibleTableExpressions,
|
||||
index++
|
||||
);
|
||||
modelParts.put( modelPart.getPartName(), modelPart );
|
||||
}
|
||||
|
@ -190,6 +195,7 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
final Set<Attribute<?, ?>> attributes = (Set<Attribute<?, ?>>) ( (ManagedDomainType<?>) ( (EntityDomainType<?>) domainType ).getIdentifierDescriptor().getSqmPathType() ).getAttributes();
|
||||
final Map<String, ModelPart> modelParts = CollectionHelper.linkedMapOfSize( attributes.size() );
|
||||
final EmbeddableValuedModelPart modelPartContainer = (EmbeddableValuedModelPart) identifierMapping;
|
||||
int index = 0;
|
||||
for ( Attribute<?, ?> attribute : attributes ) {
|
||||
if ( !( attribute instanceof SingularPersistentAttribute<?, ?> ) ) {
|
||||
throw new IllegalArgumentException( "Only embeddables without collections are supported!" );
|
||||
|
@ -203,7 +209,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
selectionExpression + "_" + attribute.getName(),
|
||||
attribute.getName(),
|
||||
modelPartContainer.findSubPart( attribute.getName(), null ),
|
||||
compatibleTableExpressions
|
||||
compatibleTableExpressions,
|
||||
index++
|
||||
);
|
||||
modelParts.put( modelPart.getPartName(), modelPart );
|
||||
}
|
||||
|
@ -222,7 +229,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
newIdentifierMapping,
|
||||
domainType,
|
||||
selectionExpression,
|
||||
existingModelPartContainer
|
||||
existingModelPartContainer,
|
||||
fetchableIndex
|
||||
);
|
||||
}
|
||||
else if ( domainType instanceof ManagedDomainType<?> ) {
|
||||
|
@ -230,6 +238,7 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
final Set<Attribute<?, ?>> attributes = (Set<Attribute<?, ?>>) ( (ManagedDomainType<?>) domainType ).getAttributes();
|
||||
final Map<String, ModelPart> modelParts = CollectionHelper.linkedMapOfSize( attributes.size() );
|
||||
final EmbeddableValuedModelPart modelPartContainer = (EmbeddableValuedModelPart) existingModelPart;
|
||||
int index = 0;
|
||||
for ( Attribute<?, ?> attribute : attributes ) {
|
||||
if ( !( attribute instanceof SingularPersistentAttribute<?, ?> ) ) {
|
||||
throw new IllegalArgumentException( "Only embeddables without collections are supported" );
|
||||
|
@ -243,11 +252,12 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
selectionExpression + "_" + attribute.getName(),
|
||||
attribute.getName(),
|
||||
modelPartContainer.findSubPart( attribute.getName(), null ),
|
||||
compatibleTableExpressions
|
||||
compatibleTableExpressions,
|
||||
index++
|
||||
);
|
||||
modelParts.put( modelPart.getPartName(), modelPart );
|
||||
}
|
||||
return new AnonymousTupleEmbeddableValuedModelPart( modelParts, domainType, selectionExpression, modelPartContainer );
|
||||
return new AnonymousTupleEmbeddableValuedModelPart( modelParts, domainType, selectionExpression, modelPartContainer, fetchableIndex );
|
||||
}
|
||||
else {
|
||||
return new AnonymousTupleBasicValuedModelPart(
|
||||
|
@ -257,7 +267,8 @@ public class AnonymousTupleTableGroupProducer implements TableGroupProducer, Map
|
|||
sqlSelections.get( selectionIndex )
|
||||
.getExpressionType()
|
||||
.getJdbcMappings()
|
||||
.get( 0 )
|
||||
.get( 0 ),
|
||||
fetchableIndex
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ public class CteTupleTableGroupProducer extends AnonymousTupleTableGroupProducer
|
|||
attributeName,
|
||||
attributeName,
|
||||
basicType,
|
||||
basicType
|
||||
basicType,
|
||||
-1
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.query.results;
|
|||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -17,7 +16,6 @@ import org.hibernate.Internal;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.internal.util.collections.StandardStack;
|
||||
import org.hibernate.metamodel.mapping.Association;
|
||||
|
@ -51,6 +49,8 @@ import org.hibernate.sql.results.graph.Fetch;
|
|||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -126,9 +126,8 @@ public class DomainResultCreationStateImpl
|
|||
return jdbcResultsMetadata;
|
||||
}
|
||||
|
||||
public NavigablePath getCurrentRelativePath() {
|
||||
final Map.Entry<String, NavigablePath> entry = relativePathStack.getCurrent();
|
||||
return entry == null ? null : entry.getValue();
|
||||
public Map.Entry<String, NavigablePath> getCurrentRelativePath() {
|
||||
return relativePathStack.getCurrent();
|
||||
}
|
||||
|
||||
public void pushExplicitFetchMementoResolver(Function<String, FetchBuilder> resolver) {
|
||||
|
@ -332,26 +331,106 @@ public class DomainResultCreationStateImpl
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitNestedFetches(FetchParent fetchParent) {
|
||||
public ImmutableFetchList visitNestedFetches(FetchParent fetchParent) {
|
||||
final FetchParent oldNestingFetchParent = this.nestingFetchParent;
|
||||
this.nestingFetchParent = fetchParent;
|
||||
final List<Fetch> fetches = visitFetches( fetchParent );
|
||||
final ImmutableFetchList fetches = visitFetches( fetchParent );
|
||||
this.nestingFetchParent = oldNestingFetchParent;
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||
public Fetch visitIdentifierFetch(EntityResultGraphNode fetchParent) {
|
||||
final EntityValuedModelPart entityValuedFetchable = fetchParent.getEntityValuedModelPart();
|
||||
final EntityIdentifierMapping identifierMapping = entityValuedFetchable.getEntityMappingType().getIdentifierMapping();
|
||||
final String identifierAttributeName = attributeName( identifierMapping );
|
||||
final Map.Entry<String, NavigablePath> oldEntry = relativePathStack.getCurrent();
|
||||
final String fullPath;
|
||||
if ( identifierMapping instanceof NonAggregatedIdentifierMapping ) {
|
||||
fullPath = oldEntry == null ? "" : oldEntry.getKey();
|
||||
}
|
||||
else {
|
||||
fullPath = oldEntry == null ?
|
||||
identifierAttributeName :
|
||||
oldEntry.getKey() + "." + identifierAttributeName;
|
||||
}
|
||||
|
||||
final Fetchable fetchable = (Fetchable) identifierMapping;
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
|
||||
.getCurrent()
|
||||
.apply( fullPath );
|
||||
DynamicFetchBuilderLegacy fetchBuilderLegacy;
|
||||
if ( explicitFetchBuilder == null ) {
|
||||
fetchBuilderLegacy = legacyFetchResolver.resolve(
|
||||
fromClauseAccess.findTableGroup( fetchParent.getNavigablePath() )
|
||||
.getPrimaryTableReference()
|
||||
.getIdentificationVariable(),
|
||||
identifierAttributeName
|
||||
);
|
||||
}
|
||||
else {
|
||||
fetchBuilderLegacy = null;
|
||||
}
|
||||
|
||||
final EntityIdentifierNavigablePath fetchPath = new EntityIdentifierNavigablePath(
|
||||
fetchParent.getNavigablePath(),
|
||||
identifierAttributeName
|
||||
);
|
||||
|
||||
final boolean processingKeyFetches = this.processingKeyFetches;
|
||||
this.processingKeyFetches = true;
|
||||
if ( identifierMapping instanceof CompositeIdentifierMapping ) {
|
||||
relativePathStack.push( new AbstractMap.SimpleEntry<>( fullPath, fetchPath ) );
|
||||
}
|
||||
|
||||
try {
|
||||
final FetchBuilder fetchBuilder;
|
||||
if ( explicitFetchBuilder != null ) {
|
||||
fetchBuilder = explicitFetchBuilder;
|
||||
}
|
||||
else {
|
||||
if ( fetchBuilderLegacy == null ) {
|
||||
fetchBuilder = Builders.implicitFetchBuilder( fetchPath, fetchable, this );
|
||||
}
|
||||
else {
|
||||
fetchBuilder = fetchBuilderLegacy;
|
||||
}
|
||||
}
|
||||
return fetchBuilder.buildFetch(
|
||||
fetchParent,
|
||||
fetchPath,
|
||||
jdbcResultsMetadata,
|
||||
(s, s2) -> {
|
||||
throw new UnsupportedOperationException();
|
||||
},
|
||||
this
|
||||
);
|
||||
}
|
||||
finally {
|
||||
this.processingKeyFetches = processingKeyFetches;
|
||||
if ( identifierMapping instanceof CompositeIdentifierMapping ) {
|
||||
this.relativePathStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableFetchList visitFetches(FetchParent fetchParent) {
|
||||
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( fetchableContainer );
|
||||
final Consumer<Fetchable> fetchableConsumer = createFetchableConsumer( fetchParent, fetches );
|
||||
fetchableContainer.visitKeyFetchables( fetchableConsumer, null );
|
||||
fetchableContainer.visitFetchables( fetchableConsumer, null );
|
||||
return fetches.build();
|
||||
}
|
||||
|
||||
final List<Fetch> fetches = CollectionHelper.arrayList( fetchableContainer.getNumberOfFetchables() );
|
||||
|
||||
final Consumer<Fetchable> fetchableConsumer = fetchable -> {
|
||||
private Consumer<Fetchable> createFetchableConsumer(FetchParent fetchParent, ImmutableFetchList.Builder fetches) {
|
||||
return fetchable -> {
|
||||
final String fetchableName = fetchable.getFetchableName();
|
||||
Map.Entry<String, NavigablePath> currentEntry;
|
||||
if ( relativePathStack.isEmpty() ) {
|
||||
currentEntry = new AbstractMap.SimpleEntry<>(
|
||||
getRelativePath( "", fetchable, fetchableContainer ),
|
||||
getRelativePath( "", fetchable ),
|
||||
new NavigablePath( fetchableName )
|
||||
);
|
||||
}
|
||||
|
@ -359,7 +438,7 @@ public class DomainResultCreationStateImpl
|
|||
final Map.Entry<String, NavigablePath> oldEntry = relativePathStack.getCurrent();
|
||||
final String key = oldEntry.getKey();
|
||||
currentEntry = new AbstractMap.SimpleEntry<>(
|
||||
getRelativePath( key, fetchable, fetchableContainer ),
|
||||
getRelativePath( key, fetchable ),
|
||||
oldEntry.getValue().append( fetchableName )
|
||||
);
|
||||
}
|
||||
|
@ -384,8 +463,9 @@ public class DomainResultCreationStateImpl
|
|||
final Association association = (Association) fetchable;
|
||||
final ForeignKeyDescriptor foreignKeyDescriptor = association.getForeignKeyDescriptor();
|
||||
|
||||
final String partName = attributeName( foreignKeyDescriptor.getSide( association.getSideNature().inverse() )
|
||||
.getModelPart());
|
||||
final String partName = attributeName(
|
||||
foreignKeyDescriptor.getSide( association.getSideNature().inverse() ).getModelPart()
|
||||
);
|
||||
|
||||
// If there are no fetch builders for this association, we only want to fetch the FK
|
||||
if ( explicitFetchBuilder == null && fetchBuilderLegacy == null && partName != null ) {
|
||||
|
@ -438,65 +518,9 @@ public class DomainResultCreationStateImpl
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
boolean previous = this.processingKeyFetches;
|
||||
this.processingKeyFetches = true;
|
||||
|
||||
if ( fetchableContainer instanceof EntityValuedModelPart ) {
|
||||
final EntityValuedModelPart entityValuedFetchable = (EntityValuedModelPart) fetchableContainer;
|
||||
final EntityIdentifierMapping identifierMapping = entityValuedFetchable.getEntityMappingType().getIdentifierMapping();
|
||||
final boolean idClass = identifierMapping instanceof NonAggregatedIdentifierMapping;
|
||||
final String identifierAttributeName = attributeName( identifierMapping );
|
||||
if ( idClass ) {
|
||||
final Map.Entry<String, NavigablePath> oldEntry = relativePathStack.getCurrent();
|
||||
relativePathStack.push(
|
||||
new AbstractMap.SimpleEntry<>(
|
||||
oldEntry == null ? "" : oldEntry.getKey(),
|
||||
new EntityIdentifierNavigablePath(
|
||||
oldEntry == null ? fetchParent.getNavigablePath() : oldEntry.getValue(),
|
||||
identifierAttributeName
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if ( identifierMapping instanceof CompositeIdentifierMapping ) {
|
||||
final Map.Entry<String, NavigablePath> oldEntry = relativePathStack.getCurrent();
|
||||
relativePathStack.push(
|
||||
new AbstractMap.SimpleEntry<>(
|
||||
oldEntry == null ?
|
||||
identifierAttributeName :
|
||||
oldEntry.getKey() + "." + identifierAttributeName,
|
||||
new EntityIdentifierNavigablePath(
|
||||
oldEntry == null ? fetchParent.getNavigablePath() : oldEntry.getValue(),
|
||||
identifierAttributeName
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
if ( identifierMapping instanceof FetchableContainer ) {
|
||||
// essentially means the entity has a composite id - ask the embeddable to visit its fetchables
|
||||
( (FetchableContainer) identifierMapping ).visitFetchables( fetchableConsumer, null );
|
||||
}
|
||||
else {
|
||||
fetchableConsumer.accept( (Fetchable) identifierMapping );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.processingKeyFetches = previous;
|
||||
if ( idClass ) {
|
||||
this.relativePathStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fetchableContainer.visitKeyFetchables( fetchableConsumer, null );
|
||||
fetchableContainer.visitFetchables( fetchableConsumer, null );
|
||||
return fetches;
|
||||
}
|
||||
|
||||
private String getRelativePath(String oldEntry, Fetchable fetchable, FetchableContainer fetchableContainer) {
|
||||
private String getRelativePath(String oldEntry, Fetchable fetchable) {
|
||||
if ( fetchable instanceof AttributeMapping || fetchable instanceof SingleAttributeIdentifierMapping || fetchable instanceof BasicValuedCollectionPart ) {
|
||||
if ( !oldEntry.equals( "" ) ) {
|
||||
return oldEntry + '.' + fetchable.getFetchableName();
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.sql.results.graph.basic.BasicFetch;
|
|||
import org.hibernate.sql.results.graph.basic.BasicResult;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
@ -248,7 +249,7 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
|||
// otherwise we assume that even if there are duplicate aliases, the values are equivalent.
|
||||
// If we don't do that, there is no way to fetch joined inheritance entities
|
||||
if ( polymorphic && ( legacyFetchBuilders == null || legacyFetchBuilders.isEmpty() )
|
||||
&& !hasJoinFetches( entityResult.getFetches() ) ) {
|
||||
&& !entityResult.hasJoinFetches() ) {
|
||||
final Set<String> aliases = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
|
||||
final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityResult.getReferencedMappingContainer()
|
||||
.getEntityPersister();
|
||||
|
@ -305,25 +306,6 @@ public class ResultSetMappingImpl implements ResultSetMapping {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean hasJoinFetches(List<Fetch> fetches) {
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
if ( fetch instanceof BasicFetch<?> || fetch.getTiming() == FetchTiming.DELAYED ) {
|
||||
// That's fine
|
||||
}
|
||||
else if ( fetch instanceof EmbeddableResultGraphNode ) {
|
||||
// Check all these fetches as well
|
||||
if ( hasJoinFetches( ( (EmbeddableResultGraphNode) fetch ).getFetches() ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private DomainResult<?> makeImplicitDomainResult(
|
||||
int valuesArrayPosition,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
|
|
|
@ -6,19 +6,11 @@
|
|||
*/
|
||||
package org.hibernate.query.results.complete;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.internal.util.MutableObject;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
|
||||
import org.hibernate.spi.EntityIdentifierNavigablePath;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
|
@ -28,10 +20,10 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.Initializer;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.entity.EntityInitializer;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityAssembler;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -42,12 +34,13 @@ public class EntityResultImpl implements EntityResult {
|
|||
|
||||
private final Fetch identifierFetch;
|
||||
private final BasicFetch<?> discriminatorFetch;
|
||||
private final List<Fetch> fetches;
|
||||
private final ImmutableFetchList fetches;
|
||||
private final boolean hasJoinFetches;
|
||||
private final boolean containsCollectionFetches;
|
||||
|
||||
private final String resultAlias;
|
||||
private final LockMode lockMode;
|
||||
|
||||
@SuppressWarnings( { "PointlessNullCheck" } )
|
||||
public EntityResultImpl(
|
||||
NavigablePath navigablePath,
|
||||
EntityValuedModelPart entityValuedModelPart,
|
||||
|
@ -78,49 +71,12 @@ public class EntityResultImpl implements EntityResult {
|
|||
}
|
||||
);
|
||||
|
||||
this.identifierFetch = creationState.visitIdentifierFetch( this );
|
||||
this.discriminatorFetch = discriminatorFetchBuilder.apply( this );
|
||||
|
||||
final List<Fetch> localFetches = creationState.visitFetches( this );
|
||||
|
||||
final EntityIdentifierMapping identifierMapping = entityValuedModelPart
|
||||
.getEntityMappingType()
|
||||
.getIdentifierMapping();
|
||||
final String idAttributeName = identifierMapping instanceof SingleAttributeIdentifierMapping
|
||||
? ( (SingleAttributeIdentifierMapping) identifierMapping ).getAttributeName()
|
||||
: null;
|
||||
|
||||
final MutableObject<Fetch> idFetchRef = new MutableObject<>();
|
||||
|
||||
for ( int i = 0; i < localFetches.size(); i++ ) {
|
||||
final Fetch fetch = localFetches.get( i );
|
||||
final String fetchLocalName = fetch.getNavigablePath().getLocalName();
|
||||
|
||||
if ( fetchLocalName.equals( EntityIdentifierMapping.ROLE_LOCAL_NAME )
|
||||
|| ( idAttributeName != null && fetchLocalName.equals( idAttributeName ) ) ) {
|
||||
// we found the id fetch
|
||||
idFetchRef.set( fetch );
|
||||
localFetches.remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.fetches = Collections.unmodifiableList( localFetches );
|
||||
|
||||
if ( idFetchRef.isNotSet() ) {
|
||||
identifierFetch = ( (Fetchable) identifierMapping ).generateFetch(
|
||||
this,
|
||||
new EntityIdentifierNavigablePath(
|
||||
navigablePath,
|
||||
ResultsHelper.attributeName( identifierMapping )
|
||||
),
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
this.identifierFetch = idFetchRef.get();
|
||||
}
|
||||
this.fetches = creationState.visitFetches( this );
|
||||
this.hasJoinFetches = fetches.hasJoinFetches();
|
||||
this.containsCollectionFetches = fetches.containsCollectionFetches();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,20 +100,23 @@ public class EntityResultImpl implements EntityResult {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
public ImmutableFetchList getFetches() {
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch findFetch(Fetchable fetchable) {
|
||||
final String name = fetchable.getFetchableName();
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
if ( fetch.getFetchedMapping().getFetchableName().equals( name ) ) {
|
||||
return fetch;
|
||||
return fetches.get( fetchable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return hasJoinFetches;
|
||||
}
|
||||
return null;
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return containsCollectionFetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -199,13 +199,13 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
|
|||
}
|
||||
}
|
||||
try {
|
||||
final NavigablePath currentRelativePath = creationState.getCurrentRelativePath();
|
||||
final Map.Entry<String, NavigablePath> currentRelativePath = creationState.getCurrentRelativePath();
|
||||
final String prefix;
|
||||
if ( currentRelativePath == null ) {
|
||||
prefix = "";
|
||||
}
|
||||
else {
|
||||
prefix = currentRelativePath.getFullPath()
|
||||
prefix = currentRelativePath.getKey()
|
||||
.replace( ELEMENT_PREFIX, "" )
|
||||
.replace( INDEX_PREFIX, "" ) + ".";
|
||||
}
|
||||
|
|
|
@ -14,13 +14,11 @@ import org.hibernate.engine.FetchTiming;
|
|||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.query.NativeQuery;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.query.results.ResultSetMappingSqlSelection;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
|
@ -28,6 +26,7 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
|
|||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
|
||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
||||
|
@ -114,7 +113,7 @@ public class DynamicFetchBuilderStandard
|
|||
creationStateImpl
|
||||
);
|
||||
}
|
||||
else if ( attributeMapping instanceof EmbeddedAttributeMapping ) {
|
||||
else if ( attributeMapping instanceof EmbeddableValuedFetchable ) {
|
||||
attributeMapping.forEachSelectable( selectableConsumer );
|
||||
return parent.generateFetchableFetch(
|
||||
attributeMapping,
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.query.results.dynamic;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
@ -279,13 +280,13 @@ public class DynamicResultBuilderEntityStandard
|
|||
}
|
||||
|
||||
try {
|
||||
final NavigablePath currentRelativePath = creationState.getCurrentRelativePath();
|
||||
final Map.Entry<String, NavigablePath> currentRelativePath = creationState.getCurrentRelativePath();
|
||||
final String prefix;
|
||||
if ( currentRelativePath == null ) {
|
||||
prefix = "";
|
||||
}
|
||||
else {
|
||||
prefix = currentRelativePath.getFullPath()
|
||||
prefix = currentRelativePath.getKey()
|
||||
.replace( ELEMENT_PREFIX, "" )
|
||||
.replace( INDEX_PREFIX, "" ) + ".";
|
||||
}
|
||||
|
|
|
@ -51,13 +51,13 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
this.fetchPath = fetchPath;
|
||||
this.fetchable = fetchable;
|
||||
final DomainResultCreationStateImpl creationStateImpl = impl( creationState );
|
||||
final NavigablePath relativePath = creationStateImpl.getCurrentRelativePath();
|
||||
final Map.Entry<String, NavigablePath> relativePath = creationStateImpl.getCurrentRelativePath();
|
||||
final Function<String, FetchBuilder> fetchBuilderResolver = creationStateImpl.getCurrentExplicitFetchMementoResolver();
|
||||
final int size = fetchable.getNumberOfFetchables();
|
||||
final Map<NavigablePath, FetchBuilder> fetchBuilders = CollectionHelper.linkedMapOfSize( size );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
final Fetchable subFetchable = fetchable.getFetchable( i );
|
||||
final NavigablePath subFetchPath = relativePath.append( subFetchable.getFetchableName() );
|
||||
final NavigablePath subFetchPath = relativePath.getValue().append( subFetchable.getFetchableName() );
|
||||
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver.apply( subFetchPath.getFullPath() );
|
||||
if ( explicitFetchBuilder == null ) {
|
||||
fetchBuilders.put(
|
||||
|
|
|
@ -48,25 +48,25 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder {
|
|||
this.fetchPath = fetchPath;
|
||||
this.fetchable = fetchable;
|
||||
final DomainResultCreationStateImpl creationStateImpl = impl( creationState );
|
||||
final NavigablePath relativePath = creationStateImpl.getCurrentRelativePath();
|
||||
final Map.Entry<String, NavigablePath> relativePath = creationStateImpl.getCurrentRelativePath();
|
||||
final Function<String, FetchBuilder> fetchBuilderResolver = creationStateImpl.getCurrentExplicitFetchMementoResolver();
|
||||
ForeignKeyDescriptor foreignKeyDescriptor = fetchable.getForeignKeyDescriptor();
|
||||
final String associationKeyPropertyName;
|
||||
final NavigablePath associationKeyFetchPath;
|
||||
if ( fetchable.getReferencedPropertyName() == null ) {
|
||||
associationKeyPropertyName = fetchable.getEntityMappingType().getIdentifierMapping().getPartName();
|
||||
associationKeyFetchPath = relativePath.append( associationKeyPropertyName );
|
||||
associationKeyFetchPath = relativePath.getValue().append( associationKeyPropertyName );
|
||||
}
|
||||
else {
|
||||
associationKeyPropertyName = fetchable.getReferencedPropertyName();
|
||||
NavigablePath path = relativePath;
|
||||
NavigablePath path = relativePath.getValue();
|
||||
for ( String part : associationKeyPropertyName.split( "\\." ) ) {
|
||||
path = path.append( part );
|
||||
}
|
||||
associationKeyFetchPath = path;
|
||||
}
|
||||
final FetchBuilder explicitAssociationKeyFetchBuilder = fetchBuilderResolver
|
||||
.apply( associationKeyFetchPath.getFullPath() );
|
||||
.apply( relativePath.getKey() + "." + associationKeyPropertyName );
|
||||
final Map<NavigablePath, FetchBuilder> fetchBuilders;
|
||||
if ( explicitAssociationKeyFetchBuilder == null ) {
|
||||
final MappingType partMappingType = foreignKeyDescriptor.getPartMappingType();
|
||||
|
|
|
@ -383,6 +383,7 @@ import org.hibernate.sql.results.graph.FetchParent;
|
|||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.sql.results.internal.SqlSelectionImpl;
|
||||
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -7137,7 +7138,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
// .getOrMakeJavaDescriptor( namedClass );
|
||||
}
|
||||
|
||||
public void addFetch(List<Fetch> fetches, FetchParent fetchParent, Fetchable fetchable, Boolean isKeyFetchable) {
|
||||
private void addFetch(ImmutableFetchList.Builder fetches, FetchParent fetchParent, Fetchable fetchable, Boolean isKeyFetchable) {
|
||||
final NavigablePath resolvedNavigablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
final Map.Entry<Integer, List<SqlSelection>> sqlSelectionsToTrack = trackedFetchSelectionsForGroup.get( resolvedNavigablePath );
|
||||
final int sqlSelectionStartIndexForFetch;
|
||||
|
@ -7333,28 +7334,28 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitNestedFetches(FetchParent fetchParent) {
|
||||
public ImmutableFetchList visitNestedFetches(FetchParent fetchParent) {
|
||||
final SqlAstQueryPartProcessingStateImpl processingState = (SqlAstQueryPartProcessingStateImpl) getCurrentProcessingState();
|
||||
final FetchParent nestingFetchParent = processingState.getNestingFetchParent();
|
||||
processingState.setNestingFetchParent( fetchParent );
|
||||
final List<Fetch> fetches = visitFetches( fetchParent );
|
||||
final ImmutableFetchList fetches = visitFetches( fetchParent );
|
||||
processingState.setNestingFetchParent( nestingFetchParent );
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> visitFetches(FetchParent fetchParent) {
|
||||
public ImmutableFetchList visitFetches(FetchParent fetchParent) {
|
||||
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
|
||||
final int keySize = referencedMappingContainer.getNumberOfKeyFetchables();
|
||||
final int size = referencedMappingContainer.getNumberOfFetchables();
|
||||
final List<Fetch> fetches = CollectionHelper.arrayList( keySize + size );
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( referencedMappingContainer );
|
||||
for ( int i = 0; i < keySize; i++ ) {
|
||||
addFetch( fetches, fetchParent, referencedMappingContainer.getKeyFetchable( i ), true );
|
||||
}
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
addFetch( fetches, fetchParent, referencedMappingContainer.getFetchable( i ), false );
|
||||
}
|
||||
return fetches;
|
||||
return fetches.build();
|
||||
}
|
||||
|
||||
private boolean shouldExplicitFetch(Integer maxDepth, Fetchable fetchable) {
|
||||
|
|
|
@ -6,12 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.EntityVersionMapping;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -21,7 +18,9 @@ public abstract class AbstractFetchParent implements FetchParent {
|
|||
private final FetchableContainer fetchContainer;
|
||||
private final NavigablePath navigablePath;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private ImmutableFetchList fetches = ImmutableFetchList.EMPTY;
|
||||
private boolean hasJoinFetches;
|
||||
private boolean containsCollectionFetches;
|
||||
|
||||
public AbstractFetchParent(FetchableContainer fetchContainer, NavigablePath navigablePath) {
|
||||
this.fetchContainer = fetchContainer;
|
||||
|
@ -29,12 +28,14 @@ public abstract class AbstractFetchParent implements FetchParent {
|
|||
}
|
||||
|
||||
public void afterInitialize(FetchParent fetchParent, DomainResultCreationState creationState) {
|
||||
assert fetches == null;
|
||||
assert fetches == ImmutableFetchList.EMPTY;
|
||||
resetFetches( creationState.visitFetches( fetchParent ) );
|
||||
}
|
||||
|
||||
protected void resetFetches(final List<Fetch> newFetches) {
|
||||
this.fetches = Collections.unmodifiableList( newFetches );
|
||||
protected void resetFetches(ImmutableFetchList newFetches) {
|
||||
this.fetches = newFetches;
|
||||
this.hasJoinFetches = newFetches.hasJoinFetches();
|
||||
this.containsCollectionFetches = newFetches.containsCollectionFetches();
|
||||
}
|
||||
|
||||
public FetchableContainer getFetchContainer() {
|
||||
|
@ -57,35 +58,25 @@ public abstract class AbstractFetchParent implements FetchParent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
return fetches == null ? Collections.emptyList() : fetches;
|
||||
public ImmutableFetchList getFetches() {
|
||||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch findFetch(final Fetchable fetchable) {
|
||||
if ( fetches == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Iterate twice so we can perform the cheapest checks on each item first:
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
if ( fetchable == fetch.getFetchedMapping() ) {
|
||||
return fetch;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fetchable instanceof EntityVersionMapping ) {
|
||||
//Second iteration performs the slightly more expensive checks, necessary for EntityVersionMapping:
|
||||
final NavigableRole navigableRole = fetchable.getNavigableRole();
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
final Fetch fetch = fetches.get( i );
|
||||
if ( fetch.getFetchedMapping().getNavigableRole().equals( navigableRole ) ) {
|
||||
return fetch;
|
||||
}
|
||||
return fetches.get( ( (EntityVersionMapping) fetchable ).getVersionAttribute() );
|
||||
}
|
||||
return fetches.get( fetchable );
|
||||
}
|
||||
|
||||
return null;
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return hasJoinFetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return containsCollectionFetches;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,22 @@ package org.hibernate.sql.results.graph;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.spi.EntityIdentifierNavigablePath;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
import static org.hibernate.query.results.ResultsHelper.attributeName;
|
||||
|
||||
/**
|
||||
* Contains state related to building {@link DomainResult} and
|
||||
|
@ -77,6 +87,39 @@ public interface DomainResultCreationState {
|
|||
*/
|
||||
ModelPart resolveModelPart(NavigablePath navigablePath);
|
||||
|
||||
default Fetch visitIdentifierFetch(EntityResultGraphNode fetchParent) {
|
||||
final EntityIdentifierMapping identifierMapping = fetchParent.getEntityValuedModelPart()
|
||||
.getEntityMappingType()
|
||||
.getIdentifierMapping();
|
||||
return fetchParent.generateFetchableFetch(
|
||||
(Fetchable) identifierMapping,
|
||||
new EntityIdentifierNavigablePath( fetchParent.getNavigablePath(), attributeName( identifierMapping ) ),
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
default BasicFetch<?> visitDiscriminatorFetch(EntityResultGraphNode fetchParent) {
|
||||
final EntityMappingType entityDescriptor = fetchParent.getEntityValuedModelPart().getEntityMappingType();
|
||||
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
|
||||
// No need to fetch the discriminator if this type does not have subclasses
|
||||
if ( discriminatorMapping != null && entityDescriptor.hasSubclasses() ) {
|
||||
return discriminatorMapping.generateFetch(
|
||||
fetchParent,
|
||||
fetchParent.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
this
|
||||
);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit fetches for the given parent.
|
||||
*
|
||||
|
@ -108,9 +151,9 @@ public interface DomainResultCreationState {
|
|||
* are built/accessed. Comes down to how we'd know whether to join fetch or select fetch. Simply pass
|
||||
* along FetchStyle?
|
||||
*/
|
||||
List<Fetch> visitFetches(FetchParent fetchParent);
|
||||
ImmutableFetchList visitFetches(FetchParent fetchParent);
|
||||
|
||||
List<Fetch> visitNestedFetches(FetchParent fetchParent);
|
||||
ImmutableFetchList visitNestedFetches(FetchParent fetchParent);
|
||||
|
||||
boolean isResolvingCircularFetch();
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.internal.log.SubSystemLogging;
|
||||
|
@ -114,12 +115,9 @@ public class DomainResultGraphPrinter {
|
|||
// visitKeyGraphNode( identifierFetch, lastInBranch );
|
||||
// }
|
||||
|
||||
final int numberOfFetches = fetchParent.getFetches().size();
|
||||
|
||||
for ( int i = 0; i < numberOfFetches; i++ ) {
|
||||
final Fetch fetch = fetchParent.getFetches().get( i );
|
||||
|
||||
final boolean lastInBranch = i + 1 == numberOfFetches;
|
||||
for ( Iterator<Fetch> iterator = fetchParent.getFetches().iterator(); iterator.hasNext(); ) {
|
||||
final Fetch fetch = iterator.next();
|
||||
final boolean lastInBranch = !iterator.hasNext();
|
||||
visitGraphNode( fetch, lastInBranch );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.sql.results.graph;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.sql.results.graph.basic.BasicFetch;
|
||||
import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
/**
|
||||
* This is essentially a List of Fetch(es), but exposing
|
||||
* an interface which is more suitable to our needs; in particular
|
||||
* it expresses the immutable nature of this structure, and allows
|
||||
* us to extend it with additional convenience methods such as
|
||||
* {@link #indexedForEach(IndexedConsumer)}.
|
||||
* And additional reason for the custom interface is to allow
|
||||
* custom implementations which can be highly optimised as
|
||||
* necessary for our specific needs; for example the
|
||||
* implementation {@link org.hibernate.sql.results.graph.internal.ImmutableFetchList}
|
||||
* is able to avoid caching problems related to JDK-8180450, which would
|
||||
* not have been possible with a standard generic container.
|
||||
* @since 6.2
|
||||
*/
|
||||
@Incubating
|
||||
public interface FetchList extends Iterable<Fetch> {
|
||||
|
||||
int size();
|
||||
|
||||
boolean isEmpty();
|
||||
|
||||
Fetch get(Fetchable fetchable);
|
||||
|
||||
void forEach(Consumer<? super Fetch> consumer);
|
||||
|
||||
void indexedForEach(IndexedConsumer<? super Fetch> consumer);
|
||||
|
||||
default Stream<Fetch> stream() {
|
||||
return StreamSupport.stream( spliterator(), false );
|
||||
}
|
||||
|
||||
default boolean hasJoinFetches() {
|
||||
for ( Fetch fetch : this ) {
|
||||
if ( fetch instanceof BasicFetch<?> || fetch.getTiming() == FetchTiming.DELAYED ) {
|
||||
// That's fine
|
||||
}
|
||||
else if ( fetch instanceof EmbeddableResultGraphNode ) {
|
||||
// Check all these fetches as well
|
||||
if ( ( (EmbeddableResultGraphNode) fetch ).hasJoinFetches() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean containsCollectionFetches() {
|
||||
for ( Fetch fetch : this ) {
|
||||
if ( fetch instanceof EagerCollectionFetch ) {
|
||||
return true;
|
||||
}
|
||||
else if ( fetch instanceof FetchParent && ( (FetchParent) fetch ).containsCollectionFetches() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
|
@ -17,6 +15,7 @@ import org.hibernate.metamodel.mapping.ModelPart;
|
|||
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
|
||||
import org.hibernate.spi.EntityIdentifierNavigablePath;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
/**
|
||||
* Contract for things that can be the parent of a fetch
|
||||
|
@ -84,10 +83,14 @@ public interface FetchParent extends DomainResultGraphNode {
|
|||
/**
|
||||
* Retrieve the fetches owned by this fetch source.
|
||||
*/
|
||||
List<Fetch> getFetches();
|
||||
ImmutableFetchList getFetches();
|
||||
|
||||
Fetch findFetch(Fetchable fetchable);
|
||||
|
||||
boolean hasJoinFetches();
|
||||
|
||||
boolean containsCollectionFetches();
|
||||
|
||||
default FetchParent getRoot() {
|
||||
if ( this instanceof Fetch ) {
|
||||
return ( (Fetch) this ).getFetchParent().getRoot();
|
||||
|
|
|
@ -8,7 +8,9 @@ package org.hibernate.sql.results.graph;
|
|||
|
||||
import org.hibernate.Incubating;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
|
||||
|
@ -24,6 +26,16 @@ public interface Fetchable extends ModelPart {
|
|||
*/
|
||||
String getFetchableName();
|
||||
|
||||
/**
|
||||
* The key that identifies this {@linkplain Fetchable} within a {@link FetchableContainer}.
|
||||
* If this {@linkplain Fetchable} is part of {@link FetchableContainer#visitFetchables(IndexedConsumer, EntityMappingType)},
|
||||
* the values is guaranteed to be between 0 (inclusive) and {@link FetchableContainer#getNumberOfFetchableKeys()} (exclusive).
|
||||
* Other {@linkplain Fetchable} objects may have a special negative value.
|
||||
* <p>
|
||||
* The main intent of this key is to index e.g. {@link Fetch} objects in an array.
|
||||
*/
|
||||
int getFetchableKey();
|
||||
|
||||
/**
|
||||
* The configured fetch timing and style
|
||||
*/
|
||||
|
|
|
@ -34,6 +34,13 @@ public interface FetchableContainer extends ModelPartContainer {
|
|||
*/
|
||||
int getNumberOfFetchables();
|
||||
|
||||
/**
|
||||
* The number of fetchables in the container
|
||||
*/
|
||||
default int getNumberOfFetchableKeys() {
|
||||
return getNumberOfFetchables();
|
||||
}
|
||||
|
||||
default Fetchable getKeyFetchable(int position) {
|
||||
List<Fetchable> fetchables = new ArrayList<>( getNumberOfKeyFetchables() );
|
||||
visitKeyFetchables( fetchable -> fetchables.add( fetchable ), null );
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.hibernate.sql.results.graph.Fetchable;
|
|||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
|
||||
import org.hibernate.sql.results.graph.collection.CollectionResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -127,8 +128,8 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
return Collections.emptyList();
|
||||
public ImmutableFetchList getFetches() {
|
||||
return ImmutableFetchList.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -136,4 +137,14 @@ public class CollectionDomainResult implements DomainResult, CollectionResultGra
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,11 +23,13 @@ import org.hibernate.sql.results.graph.DomainResult;
|
|||
import org.hibernate.sql.results.graph.DomainResultAssembler;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchList;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
import org.hibernate.sql.results.graph.FetchParentAccess;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
import org.hibernate.sql.results.graph.collection.CollectionInitializer;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -40,7 +42,7 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
|
|||
private final Fetch elementFetch;
|
||||
private final Fetch indexFetch;
|
||||
|
||||
private final List<Fetch> fetches;
|
||||
private final ImmutableFetchList fetches;
|
||||
|
||||
private final CollectionInitializerProducer initializerProducer;
|
||||
|
||||
|
@ -104,17 +106,17 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
|
|||
creationState
|
||||
);
|
||||
|
||||
fetches = Collections.unmodifiableList( creationState.visitFetches( this ) );
|
||||
fetches = creationState.visitFetches( this );
|
||||
if ( fetchedAttribute.getIndexDescriptor() != null ) {
|
||||
assert fetches.size() == 2;
|
||||
indexFetch = fetches.get( 0 );
|
||||
elementFetch = fetches.get( 1 );
|
||||
indexFetch = fetches.get( fetchedAttribute.getIndexDescriptor() );
|
||||
elementFetch = fetches.get( fetchedAttribute.getElementDescriptor() );
|
||||
}
|
||||
else {
|
||||
if ( !fetches.isEmpty() ) { // might be empty due to fetch depth limit
|
||||
assert fetches.size() == 1;
|
||||
indexFetch = null;
|
||||
elementFetch = fetches.get( 0 );
|
||||
elementFetch = fetches.get( fetchedAttribute.getElementDescriptor() );
|
||||
}
|
||||
else {
|
||||
indexFetch = null;
|
||||
|
@ -180,7 +182,7 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
public ImmutableFetchList getFetches() {
|
||||
return fetches;
|
||||
}
|
||||
|
||||
|
@ -200,6 +202,18 @@ public class EagerCollectionFetch extends CollectionFetch implements FetchParent
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
// This is already a fetch, so this line should actually never be hit
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
// This is already a collection fetch, so this line should actually never be hit
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaType<?> getResultJavaType() {
|
||||
return getFetchedMapping().getJavaType();
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResult;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.AggregateJdbcType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -106,9 +107,9 @@ public class AggregateEmbeddableResultImpl<T> extends AbstractFetchParent implem
|
|||
this.containsAnyNonScalars = determineIfContainedAnyScalars( getFetches() );
|
||||
}
|
||||
|
||||
private static boolean determineIfContainedAnyScalars(List<Fetch> fetches) {
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
if ( fetches.get( i ).containsAnyNonScalarResults() ) {
|
||||
private static boolean determineIfContainedAnyScalars(ImmutableFetchList fetches) {
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch.containsAnyNonScalarResults() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,23 +6,15 @@
|
|||
*/
|
||||
package org.hibernate.sql.results.graph.embeddable.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.results.graph.AbstractFetchParent;
|
||||
import org.hibernate.sql.results.graph.AssemblerCreationState;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
|
@ -34,6 +26,7 @@ import org.hibernate.sql.results.graph.basic.BasicFetch;
|
|||
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResult;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -53,7 +46,7 @@ public class EmbeddableExpressionResultImpl<T> extends AbstractFetchParent imple
|
|||
super( modelPart.getEmbeddableTypeDescriptor(), navigablePath );
|
||||
this.resultVariable = resultVariable;
|
||||
|
||||
final List<Fetch> fetches = new ArrayList<>();
|
||||
final ImmutableFetchList.Builder fetches = new ImmutableFetchList.Builder( modelPart );
|
||||
final EmbeddableMappingType mappingType = modelPart.getEmbeddableTypeDescriptor();
|
||||
final int numberOfAttributeMappings = mappingType.getNumberOfAttributeMappings();
|
||||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
|
@ -81,13 +74,13 @@ public class EmbeddableExpressionResultImpl<T> extends AbstractFetchParent imple
|
|||
);
|
||||
}
|
||||
|
||||
this.containsAnyNonScalars = determineIfContainedAnyScalars( fetches );
|
||||
resetFetches( fetches );
|
||||
resetFetches( fetches.build() );
|
||||
this.containsAnyNonScalars = determineIfContainedAnyScalars( getFetches() );
|
||||
}
|
||||
|
||||
private static boolean determineIfContainedAnyScalars(List<Fetch> fetches) {
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
if ( fetches.get( i ).containsAnyNonScalarResults() ) {
|
||||
private static boolean determineIfContainedAnyScalars(ImmutableFetchList fetches) {
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch.containsAnyNonScalarResults() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.hibernate.sql.results.graph.FetchParentAccess;
|
|||
import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResult;
|
||||
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
|
||||
/**
|
||||
|
@ -76,9 +77,9 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
|
|||
containsAnyNonScalars = determineIfContainedAnyScalars( getFetches() );
|
||||
}
|
||||
|
||||
private static boolean determineIfContainedAnyScalars(List<Fetch> fetches) {
|
||||
for ( int i = 0; i < fetches.size(); i++ ) {
|
||||
if ( fetches.get( i ).containsAnyNonScalarResults() ) {
|
||||
private static boolean determineIfContainedAnyScalars(ImmutableFetchList fetches) {
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch.containsAnyNonScalarResults() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,37 +53,20 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
final NavigablePath navigablePath = getNavigablePath();
|
||||
final TableGroup entityTableGroup = creationState.getSqlAstCreationState().getFromClauseAccess()
|
||||
.getTableGroup( navigablePath );
|
||||
final EntityIdentifierNavigablePath identifierNavigablePath = new EntityIdentifierNavigablePath( navigablePath, attributeName( identifierMapping ) );
|
||||
if ( navigablePath.getParent() == null && !creationState.forceIdentifierSelection() ) {
|
||||
identifierFetch = null;
|
||||
visitIdentifierMapping( identifierNavigablePath, creationState, identifierMapping, entityTableGroup );
|
||||
visitIdentifierMapping(
|
||||
new EntityIdentifierNavigablePath( navigablePath, attributeName( identifierMapping ) ),
|
||||
creationState,
|
||||
identifierMapping,
|
||||
entityTableGroup
|
||||
);
|
||||
}
|
||||
else {
|
||||
identifierFetch = ( (Fetchable) identifierMapping ).generateFetch(
|
||||
fetchParent,
|
||||
identifierNavigablePath,
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
identifierFetch = creationState.visitIdentifierFetch( this );
|
||||
}
|
||||
|
||||
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
|
||||
// No need to fetch the discriminator if this type does not have subclasses
|
||||
if ( discriminatorMapping != null && entityDescriptor.hasSubclasses() ) {
|
||||
discriminatorFetch = discriminatorMapping.generateFetch(
|
||||
fetchParent,
|
||||
navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ),
|
||||
FetchTiming.IMMEDIATE,
|
||||
true,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
else {
|
||||
discriminatorFetch = null;
|
||||
}
|
||||
discriminatorFetch = creationState.visitDiscriminatorFetch( this );
|
||||
|
||||
final EntityRowIdMapping rowIdMapping = entityDescriptor.getRowIdMapping();
|
||||
if ( rowIdMapping == null ) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import org.hibernate.sql.results.graph.FetchParent;
|
|||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.entity.EntityFetch;
|
||||
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -55,8 +56,8 @@ public abstract class AbstractNonJoinedEntityFetch implements EntityFetch {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Fetch> getFetches() {
|
||||
return Collections.emptyList();
|
||||
public ImmutableFetchList getFetches() {
|
||||
return ImmutableFetchList.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,6 +65,16 @@ public abstract class AbstractNonJoinedEntityFetch implements EntityFetch {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasJoinFetches() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsCollectionFetches() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityMappingType getReferencedMappingType() {
|
||||
return fetchedModelPart.getEntityMappingType();
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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.sql.results.graph.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.persister.internal.ImmutableAttributeMappingList;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.FetchList;
|
||||
import org.hibernate.sql.results.graph.Fetchable;
|
||||
import org.hibernate.sql.results.graph.FetchableContainer;
|
||||
|
||||
public final class ImmutableFetchList implements FetchList {
|
||||
|
||||
public static ImmutableFetchList EMPTY = new ImmutableFetchList();
|
||||
private final Fetch[] fetches;
|
||||
|
||||
private ImmutableFetchList() {
|
||||
this.fetches = null;
|
||||
}
|
||||
|
||||
private ImmutableFetchList(Fetch[] fetches) {
|
||||
assert fetches != null;
|
||||
this.fetches = fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if ( fetches == null ) {
|
||||
return 0;
|
||||
}
|
||||
int size = 0;
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch != null ) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return fetches == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch get(Fetchable fetchable) {
|
||||
return fetches == null ? null : fetches[fetchable.getFetchableKey()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super Fetch> consumer) {
|
||||
if ( fetches != null ) {
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch != null ) {
|
||||
consumer.accept( fetch );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indexedForEach(IndexedConsumer<? super Fetch> consumer) {
|
||||
if ( fetches != null ) {
|
||||
int index = 0;
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch != null ) {
|
||||
consumer.accept( index++, fetch );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Fetch> iterator() {
|
||||
if ( fetches == null ) {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
return new FetchIterator();
|
||||
}
|
||||
|
||||
private final class FetchIterator implements Iterator<Fetch> {
|
||||
|
||||
private int idx;
|
||||
|
||||
public FetchIterator() {
|
||||
assert ImmutableFetchList.this.fetches != null;
|
||||
this.idx = 0;
|
||||
while (ImmutableFetchList.this.fetches[idx] == null) {
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return idx < ImmutableFetchList.this.fetches.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch next() {
|
||||
final Fetch fetch = ImmutableFetchList.this.fetches[idx++];
|
||||
while ( idx < ImmutableFetchList.this.fetches.length ) {
|
||||
if ( ImmutableFetchList.this.fetches[idx] != null ) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return fetch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final Fetch[] fetches;
|
||||
|
||||
public Builder(FetchableContainer container) {
|
||||
this.fetches = new Fetch[container.getNumberOfFetchableKeys()];
|
||||
}
|
||||
|
||||
public void add(Fetch fetch) {
|
||||
fetches[fetch.getFetchedMapping().getFetchableKey()] = fetch;
|
||||
}
|
||||
|
||||
public ImmutableFetchList build() {
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch != null ) {
|
||||
return new ImmutableFetchList( fetches );
|
||||
}
|
||||
}
|
||||
return EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,8 +12,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.internal.FetchingScrollableResultsImpl;
|
||||
import org.hibernate.internal.ScrollableResultsImpl;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValues;
|
||||
|
@ -74,17 +72,11 @@ public class ScrollableResultsConsumer<R> implements ResultsConsumer<ScrollableR
|
|||
|
||||
private boolean containsCollectionFetches(JdbcValuesMapping valuesMapping) {
|
||||
final List<DomainResult<?>> domainResults = valuesMapping.getDomainResults();
|
||||
for ( DomainResult domainResult : domainResults ) {
|
||||
if ( domainResult instanceof EntityResult ) {
|
||||
EntityResult entityResult = (EntityResult) domainResult;
|
||||
final List<Fetch> fetches = entityResult.getFetches();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
if ( fetch instanceof EagerCollectionFetch ) {
|
||||
for ( DomainResult<?> domainResult : domainResults ) {
|
||||
if ( domainResult instanceof EntityResult && ( (EntityResult) domainResult ).containsCollectionFetches() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.hibernate.sql.results.graph.entity.EntityFetch;
|
|||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchImpl;
|
||||
import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
|
@ -190,13 +191,12 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
|
|||
Fetchable fetchable = getFetchable( "company", Person.class );
|
||||
|
||||
final Fetch companyFetch = ownerEntityResult.findFetch( fetchable );
|
||||
List<Fetch> fetches = ownerEntityResult.getFetches();
|
||||
assertThat( companyFetch, notNullValue() );
|
||||
|
||||
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
|
||||
assertThat( companyEntityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( companyEntityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().get( 0 );
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().iterator().next();
|
||||
assertThat( shipAddressesFetch.getFetchedMapping().getPartName(), is( "shipAddresses" ) );
|
||||
assertThat( shipAddressesFetch, instanceOf( DelayedCollectionFetch.class ) );
|
||||
} );
|
||||
|
@ -348,9 +348,9 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
|
|||
|
||||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
assertThat( entityResult.getReferencedModePart().getJavaType().getJavaTypeClass(), assignableTo( expectedEntityJpaClass ) );
|
||||
assertThat( entityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( entityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch fetch = entityResult.getFetches().get( 0 );
|
||||
final Fetch fetch = entityResult.getFetches().iterator().next();
|
||||
assertThat( fetch, instanceOf( EntityFetch.class ) );
|
||||
|
||||
final EntityFetch entityFetch = (EntityFetch) fetch;
|
||||
|
|
|
@ -189,9 +189,9 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
|
|||
assertThat( companyFetch, notNullValue() );
|
||||
|
||||
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
|
||||
assertThat( companyEntityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( companyEntityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().get( 0 );
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().iterator().next();
|
||||
assertThat( shipAddressesFetch.getFetchedMapping().getPartName(), is( "shipAddresses" ) );
|
||||
assertThat( shipAddressesFetch, instanceOf( DelayedCollectionFetch.class ) );
|
||||
} );
|
||||
|
@ -337,9 +337,9 @@ public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware
|
|||
|
||||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
assertThat( entityResult.getReferencedModePart().getJavaType().getJavaTypeClass(), assignableTo( expectedEntityJpaClass ) );
|
||||
assertThat( entityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( entityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch fetch = entityResult.getFetches().get( 0 );
|
||||
final Fetch fetch = entityResult.getFetches().iterator().next();
|
||||
assertThat( fetch, instanceOf( EntityFetch.class ) );
|
||||
|
||||
final EntityFetch entityFetch = (EntityFetch) fetch;
|
||||
|
|
|
@ -191,9 +191,9 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
|
|||
assertThat( companyFetch, notNullValue() );
|
||||
|
||||
final EntityResult companyEntityResult = ( (EntityFetchJoinedImpl) companyFetch).getEntityResult();
|
||||
assertThat( companyEntityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( companyEntityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().get( 0 );
|
||||
final Fetch shipAddressesFetch = companyEntityResult.getFetches().iterator().next();
|
||||
assertThat( shipAddressesFetch.getFetchedMapping().getPartName(), is( "shipAddresses" ) );
|
||||
assertThat( shipAddressesFetch, instanceOf( DelayedCollectionFetch.class ) );
|
||||
} );
|
||||
|
@ -345,9 +345,9 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
|
|||
|
||||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
assertThat( entityResult.getReferencedModePart().getJavaType().getJavaTypeClass(), assignableTo( expectedEntityJpaClass ) );
|
||||
assertThat( entityResult.getFetches(), hasSize( 1 ) );
|
||||
assertThat( entityResult.getFetches().size(), is( 1 ) );
|
||||
|
||||
final Fetch fetch = entityResult.getFetches().get( 0 );
|
||||
final Fetch fetch = entityResult.getFetches().iterator().next();
|
||||
assertThat( fetch, instanceOf( EntityFetch.class ) );
|
||||
|
||||
final EntityFetch entityFetch = (EntityFetch) fetch;
|
||||
|
|
|
@ -73,12 +73,12 @@ public class LoadPlanBuilderTest {
|
|||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
assertThat( entityResult.getFetches() ).hasSize( 2 );
|
||||
|
||||
final Fetch txtFetch = entityResult.getFetches().get( 0 );
|
||||
final Fetch txtFetch = entityResult.getFetches().get( entityDescriptor.findAttributeMapping( "msgTxt" ) );
|
||||
assertThat( txtFetch ).isNotNull();
|
||||
assertThat( txtFetch.getFetchedMapping().getFetchableName() ).isEqualTo( "msgTxt" );
|
||||
assertThat( txtFetch.getTiming() ).isEqualTo( FetchTiming.IMMEDIATE );
|
||||
|
||||
final Fetch posterFetch = entityResult.getFetches().get( 1 );
|
||||
final Fetch posterFetch = entityResult.getFetches().get( entityDescriptor.findAttributeMapping( "poster" ) );
|
||||
assertThat( posterFetch ).isNotNull();
|
||||
assertThat( posterFetch.getFetchedMapping().getFetchableName() ).isEqualTo( "poster" );
|
||||
assertThat( posterFetch.getTiming() ).isEqualTo( FetchTiming.DELAYED );
|
||||
|
@ -114,12 +114,12 @@ public class LoadPlanBuilderTest {
|
|||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
assertThat( entityResult.getFetches() ).hasSize( 2 );
|
||||
|
||||
final Fetch txtFetch = entityResult.getFetches().get( 0 );
|
||||
final Fetch txtFetch = entityResult.getFetches().get( entityDescriptor.findAttributeMapping( "msgTxt" ) );
|
||||
assertThat( txtFetch ).isNotNull();
|
||||
assertThat( txtFetch.getFetchedMapping().getFetchableName() ).isEqualTo( "msgTxt" );
|
||||
assertThat( txtFetch.getTiming() ).isEqualTo( FetchTiming.IMMEDIATE );
|
||||
|
||||
final Fetch posterFetch = entityResult.getFetches().get( 1 );
|
||||
final Fetch posterFetch = entityResult.getFetches().get( entityDescriptor.findAttributeMapping( "poster" ) );
|
||||
assertThat( posterFetch ).isNotNull();
|
||||
assertThat( posterFetch.getFetchedMapping().getFetchableName() ).isEqualTo( "poster" );
|
||||
assertThat( posterFetch.getTiming() ).isEqualTo( FetchTiming.IMMEDIATE );
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.sql.results.graph.collection.internal.EagerCollectionFetch;
|
|||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.entity.EntityResult;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
|
@ -85,22 +86,22 @@ public class MappedFetchTests {
|
|||
assertThat( domainResult, instanceOf( EntityResult.class ) );
|
||||
|
||||
final EntityResult entityResult = (EntityResult) domainResult;
|
||||
final List<Fetch> fetches = entityResult.getFetches();
|
||||
final ImmutableFetchList fetches = entityResult.getFetches();
|
||||
|
||||
// name + both lists
|
||||
assertThat( fetches.size(), is( 3 ) );
|
||||
|
||||
// order is alphabetical...
|
||||
|
||||
final Fetch nameFetch = fetches.get( 0 );
|
||||
final Fetch nameFetch = fetches.get( rootEntityDescriptor.findAttributeMapping( "name" ) );
|
||||
assertThat( nameFetch.getFetchedMapping().getFetchableName(), is( "name" ) );
|
||||
assertThat( nameFetch, instanceOf( BasicFetch.class ) );
|
||||
|
||||
final Fetch nickNamesFetch = fetches.get( 1 );
|
||||
final Fetch nickNamesFetch = fetches.get( rootEntityDescriptor.findAttributeMapping( "nickNames" ) );
|
||||
assertThat( nickNamesFetch.getFetchedMapping().getFetchableName(), is( "nickNames" ) );
|
||||
assertThat( nickNamesFetch, instanceOf( EagerCollectionFetch.class ) );
|
||||
|
||||
final Fetch simpleEntitiesFetch = fetches.get( 2 );
|
||||
final Fetch simpleEntitiesFetch = fetches.get( rootEntityDescriptor.findAttributeMapping( "simpleEntities" ) );
|
||||
assertThat( simpleEntitiesFetch.getFetchedMapping().getFetchableName(), is( "simpleEntities" ) );
|
||||
assertThat( simpleEntitiesFetch, instanceOf( DelayedCollectionFetch.class ) );
|
||||
|
||||
|
|
Loading…
Reference in New Issue