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