HHH-15636 Indexed Fetchable access via IndexedConsumer and by position and get rid of some capturing lambdas

This commit is contained in:
Christian Beikov 2022-10-28 12:13:45 +02:00
parent 53076f3029
commit 2f4712909a
34 changed files with 610 additions and 391 deletions

View File

@ -146,9 +146,9 @@ public class EnhancementAsProxyLazinessInterceptor extends AbstractLazyLoadInter
if ( writtenValues != null ) { if ( writtenValues != null ) {
// here is the replaying of the explicitly set values we prepared above // here is the replaying of the explicitly set values we prepared above
for ( String writtenFieldName : writtenFieldNames ) { for ( String writtenFieldName : writtenFieldNames ) {
List<AttributeMapping> attributeMappings = entityPersister.getAttributeMappings(); final int size = entityPersister.getNumberOfAttributeMappings();
for ( int index = 0; index < attributeMappings.size(); index++ ) { for ( int index = 0; index < size; index++ ) {
if ( writtenFieldName.contains( attributeMappings.get( index ).getAttributeName() ) ) { if ( writtenFieldName.contains( entityPersister.getAttributeMapping( index ).getAttributeName() ) ) {
entityPersister.setValue( entityPersister.setValue(
target, target,
index, index,

View File

@ -30,6 +30,7 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.loader.entity.CacheEntityLoaderHelper.PersistenceContextEntry; import org.hibernate.loader.entity.CacheEntityLoaderHelper.PersistenceContextEntry;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
@ -118,9 +119,9 @@ public class DefaultLoadEventListener implements LoadEventListener {
final EntityIdentifierMapping idMapping = persister.getIdentifierMapping(); final EntityIdentifierMapping idMapping = persister.getIdentifierMapping();
if ( idMapping instanceof CompositeIdentifierMapping ) { if ( idMapping instanceof CompositeIdentifierMapping ) {
final CompositeIdentifierMapping compositeIdMapping = (CompositeIdentifierMapping) idMapping; final CompositeIdentifierMapping compositeIdMapping = (CompositeIdentifierMapping) idMapping;
final List<AttributeMapping> attributeMappings = compositeIdMapping.getPartMappingType().getAttributeMappings(); final EmbeddableMappingType partMappingType = compositeIdMapping.getPartMappingType();
if ( attributeMappings.size() == 1 ) { if ( partMappingType.getNumberOfAttributeMappings() == 1 ) {
final AttributeMapping singleIdAttribute = attributeMappings.get( 0 ); final AttributeMapping singleIdAttribute = partMappingType.getAttributeMapping( 0 );
if ( singleIdAttribute.getMappedType() instanceof EntityMappingType ) { if ( singleIdAttribute.getMappedType() instanceof EntityMappingType ) {
final EntityMappingType parentIdTargetMapping = (EntityMappingType) singleIdAttribute.getMappedType(); final EntityMappingType parentIdTargetMapping = (EntityMappingType) singleIdAttribute.getMappedType();
final EntityIdentifierMapping parentIdTargetIdMapping = parentIdTargetMapping.getIdentifierMapping(); final EntityIdentifierMapping parentIdTargetIdMapping = parentIdTargetMapping.getIdentifierMapping();

View File

@ -54,6 +54,9 @@ import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect; import org.hibernate.sql.exec.spi.JdbcSelect;
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.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.spi.ListResultsConsumer; import org.hibernate.sql.results.spi.ListResultsConsumer;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
@ -99,25 +102,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
null, null,
creationState creationState
), ),
(fetchParent, querySpec, creationState) -> { AbstractNaturalIdLoader::visitFetches,
final List<Fetch> fetches = new ArrayList<>( naturalIdMapping.getNaturalIdAttributes().size() );
fetchParent.getReferencedMappingContainer().visitFetchables(
fetchable -> {
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
navigablePath,
fetchable.getMappedFetchOptions().getTiming(),
true,
null,
creationState
);
fetches.add( fetch );
},
entityDescriptor
);
return fetches;
},
(statsEnabled) -> { (statsEnabled) -> {
// entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE ); // entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE );
return statsEnabled ? System.nanoTime() : -1; return statsEnabled ? System.nanoTime() : -1;
@ -326,27 +311,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
null, null,
creationState creationState
), ),
(fetchParent, querySpec, creationState) -> { AbstractNaturalIdLoader::visitFetches,
final List<Fetch> fetches = new ArrayList<>();
fetchParent.getReferencedMappingContainer().visitFetchables(
(fetchable) -> {
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
navigablePath,
fetchable.getMappedFetchOptions().getTiming(),
true,
null,
creationState
);
fetches.add( fetch );
},
null
);
return fetches;
},
(statsEnabled) -> { (statsEnabled) -> {
// entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE ); // entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE );
return statsEnabled ? System.nanoTime() : -1L; return statsEnabled ? System.nanoTime() : -1L;
@ -455,4 +420,27 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
return results.get( 0 ); return results.get( 0 );
} }
private static List<Fetch> visitFetches(
FetchParent fetchParent,
QuerySpec querySpec,
LoaderSqlAstCreationState creationState) {
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
final int size = fetchableContainer.getNumberOfFetchables();
final List<Fetch> fetches = new ArrayList<>( size );
for ( int i = 0; i < size; i++ ) {
final Fetchable fetchable = fetchableContainer.getFetchable( i );
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
navigablePath,
fetchable.getMappedFetchOptions().getTiming(),
true,
null,
creationState
);
fetches.add( fetch );
}
return fetches;
}
} }

View File

@ -674,11 +674,15 @@ public class LoaderSelectBuilder {
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer(); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
if ( fetchParent.getNavigablePath().getParent() != null ) { if ( fetchParent.getNavigablePath().getParent() != null ) {
referencedMappingContainer.visitKeyFetchables( final int size = referencedMappingContainer.getNumberOfKeyFetchables();
fetchable -> processor.accept( fetchable, true ), null ); for ( int i = 0; i < size; i++ ) {
processor.accept( referencedMappingContainer.getKeyFetchable( i ), true );
}
}
final int size = referencedMappingContainer.getNumberOfFetchables();
for ( int i = 0; i < size; i++ ) {
processor.accept( referencedMappingContainer.getFetchable( i ), false );
} }
referencedMappingContainer.visitFetchables(
fetchable -> processor.accept( fetchable, false ), null );
return fetches; return fetches;
} }

View File

@ -194,9 +194,10 @@ public abstract class AbstractCompositeIdentifierMapping
JdbcValuesConsumer valuesConsumer, JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
int span = 0; int span = 0;
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings(); final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
for ( int i = 0; i < attributeMappings.size(); i++ ) { final int size = embeddableTypeDescriptor.getNumberOfAttributeMappings();
final AttributeMapping attributeMapping = attributeMappings.get( i ); for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
if ( attributeMapping instanceof ToOneAttributeMapping ) { if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;

View File

@ -41,6 +41,7 @@ import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.results.graph.DomainResult; 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.Fetchable;
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;
@ -466,6 +467,11 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
return getEntityPersister().getNumberOfFetchables(); return getEntityPersister().getNumberOfFetchables();
} }
@Override
default Fetchable getFetchable(int position) {
return getEntityPersister().getFetchable( position );
}
@Override @Override
default void applyDiscriminator( default void applyDiscriminator(
Consumer<Predicate> predicateConsumer, Consumer<Predicate> predicateConsumer,

View File

@ -134,13 +134,17 @@ public class MappingModelHelper {
else if ( attribute1 instanceof EmbeddableValuedModelPart ) { else if ( attribute1 instanceof EmbeddableValuedModelPart ) {
final EmbeddableValuedModelPart embedded1 = (EmbeddableValuedModelPart) attribute1; final EmbeddableValuedModelPart embedded1 = (EmbeddableValuedModelPart) attribute1;
final EmbeddableValuedModelPart embedded2 = (EmbeddableValuedModelPart) attribute2; final EmbeddableValuedModelPart embedded2 = (EmbeddableValuedModelPart) attribute2;
final List<AttributeMapping> attrs1 = embedded1.getEmbeddableTypeDescriptor().getAttributeMappings(); final EmbeddableMappingType embeddableTypeDescriptor1 = embedded1.getEmbeddableTypeDescriptor();
final List<AttributeMapping> attrs2 = embedded2.getEmbeddableTypeDescriptor().getAttributeMappings(); final EmbeddableMappingType embeddableTypeDescriptor2 = embedded2.getEmbeddableTypeDescriptor();
if ( attrs1.size() != attrs2.size() ) { final int numberOfAttributeMappings = embeddableTypeDescriptor1.getNumberOfAttributeMappings();
if ( numberOfAttributeMappings != embeddableTypeDescriptor2.getNumberOfAttributeMappings() ) {
return false; return false;
} }
for ( int i = 0; i < attrs1.size(); i++ ) { for ( int i = 0; i < numberOfAttributeMappings; i++ ) {
if ( !isCompatibleModelPart( attrs1.get( i ), attrs2.get( i ) ) ) { if ( !isCompatibleModelPart(
embeddableTypeDescriptor1.getAttributeMapping( i ),
embeddableTypeDescriptor2.getAttributeMapping( i )
) ) {
return false; return false;
} }
} }

View File

@ -12,6 +12,7 @@ import java.util.function.Consumer;
import org.hibernate.Filter; import org.hibernate.Filter;
import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment; import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
@ -66,11 +67,51 @@ public interface PluralAttributeMapping
} }
} }
@Override
default int getNumberOfKeyFetchables() {
return getIndexDescriptor() == null ? 0 : 1;
}
@Override
default Fetchable getKeyFetchable(int position) {
final CollectionPart indexDescriptor = getIndexDescriptor();
if ( indexDescriptor != null && position == 0 ) {
return indexDescriptor;
}
throw new IndexOutOfBoundsException( position );
}
@Override
default void visitKeyFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
final CollectionPart indexDescriptor = getIndexDescriptor();
if ( indexDescriptor != null ) {
fetchableConsumer.accept( 0, indexDescriptor );
}
}
@Override @Override
default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) { default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( getElementDescriptor() ); fetchableConsumer.accept( getElementDescriptor() );
} }
@Override
default int getNumberOfFetchables() {
return 1;
}
@Override
default void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( 0, getElementDescriptor() );
}
@Override
default Fetchable getFetchable(int position) {
if ( position == 0 ) {
return getElementDescriptor();
}
throw new IndexOutOfBoundsException( position );
}
@SuppressWarnings({ "unchecked", "rawtypes" }) @SuppressWarnings({ "unchecked", "rawtypes" })
@Override @Override
default <T> DomainResult<T> createSnapshotDomainResult( default <T> DomainResult<T> createSnapshotDomainResult(

View File

@ -29,6 +29,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SortSpecification; import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.sql.results.graph.Fetchable;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
@ -86,13 +87,12 @@ public abstract class AbstractDomainPath implements DomainPath {
final EmbeddableValuedModelPart embeddableValuedModelPart = (EmbeddableValuedModelPart) referenceModelPart; final EmbeddableValuedModelPart embeddableValuedModelPart = (EmbeddableValuedModelPart) referenceModelPart;
if ( embeddableValuedModelPart.getFetchableName() if ( embeddableValuedModelPart.getFetchableName()
.equals( modelPartName ) || ELEMENT_TOKEN.equals( modelPartName ) ) { .equals( modelPartName ) || ELEMENT_TOKEN.equals( modelPartName ) ) {
final List<Expression> expressions = new ArrayList<>( embeddableValuedModelPart.getNumberOfFetchables() ); final int size = embeddableValuedModelPart.getNumberOfFetchables();
embeddableValuedModelPart.visitFetchables( final List<Expression> expressions = new ArrayList<>( size );
fetchable -> { for ( int i = 0; i < size; i++ ) {
expressions.add( resolve( fetchable, ast, tableGroup, modelPartName, creationState ) ); final Fetchable fetchable = embeddableValuedModelPart.getFetchable( i );
}, expressions.add( resolve( fetchable, ast, tableGroup, modelPartName, creationState ) );
null }
);
return new SqlTuple( expressions, embeddableValuedModelPart ); return new SqlTuple( expressions, embeddableValuedModelPart );
} }
else { else {

View File

@ -136,7 +136,8 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
MappingModelCreationProcess creationProcess, MappingModelCreationProcess creationProcess,
ManagedMappingType declaringType, ManagedMappingType declaringType,
List<? extends AttributeMapping> attributeMappings) { List<? extends AttributeMapping> attributeMappings) {
if ( inverseMappingType.getAttributeMappings().isEmpty() ) { final int size = inverseMappingType.getNumberOfAttributeMappings();
if ( size == 0 ) {
return false; return false;
} }
//noinspection unchecked //noinspection unchecked
@ -145,7 +146,8 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
mappings.clear(); mappings.clear();
int currentIndex = 0; int currentIndex = 0;
// We copy the attributes from the inverse mappings and replace the selection mappings // We copy the attributes from the inverse mappings and replace the selection mappings
for ( AttributeMapping attributeMapping : inverseMappingType.getAttributeMappings() ) { for ( int j = 0; j < size; j++ ) {
AttributeMapping attributeMapping = inverseMappingType.getAttributeMapping( j );
if ( attributeMapping instanceof BasicAttributeMapping ) { if ( attributeMapping instanceof BasicAttributeMapping ) {
final BasicAttributeMapping original = (BasicAttributeMapping) attributeMapping; final BasicAttributeMapping original = (BasicAttributeMapping) attributeMapping;
final SelectableMapping selectableMapping = selectableMappings.getSelectable( currentIndex ); final SelectableMapping selectableMapping = selectableMappings.getSelectable( currentIndex );
@ -161,7 +163,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
else if ( attributeMapping instanceof ToOneAttributeMapping ) { else if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping original = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping original = (ToOneAttributeMapping) attributeMapping;
ForeignKeyDescriptor foreignKeyDescriptor = original.getForeignKeyDescriptor(); ForeignKeyDescriptor foreignKeyDescriptor = original.getForeignKeyDescriptor();
if ( foreignKeyDescriptor==null ) { if ( foreignKeyDescriptor == null ) {
// This is expected to happen when processing a // This is expected to happen when processing a
// PostInitCallbackEntry because the callbacks // PostInitCallbackEntry because the callbacks
// are not ordered. The exception is caught in // are not ordered. The exception is caught in
@ -191,7 +193,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
} }
else if ( attributeMapping instanceof EmbeddableValuedModelPart ) { else if ( attributeMapping instanceof EmbeddableValuedModelPart ) {
final SelectableMapping[] subMappings = new SelectableMapping[attributeMapping.getJdbcTypeCount()]; final SelectableMapping[] subMappings = new SelectableMapping[attributeMapping.getJdbcTypeCount()];
for (int i = 0; i < subMappings.length; i++) { for ( int i = 0; i < subMappings.length; i++ ) {
subMappings[i] = selectableMappings.getSelectable( currentIndex++ ); subMappings[i] = selectableMappings.getSelectable( currentIndex++ );
} }
attributeMapping = MappingModelCreationHelper.createInverseModelPart( attributeMapping = MappingModelCreationHelper.createInverseModelPart(

View File

@ -422,6 +422,11 @@ public class CompoundNaturalIdMapping extends AbstractNaturalIdMapping implement
return attributes.size(); return attributes.size();
} }
@Override
public Fetchable getFetchable(int position) {
return attributes.get( position );
}
@Override @Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
for ( int i = 0; i < attributes.size(); i++ ) { for ( int i = 0; i < attributes.size(); i++ ) {

View File

@ -184,6 +184,17 @@ public class DiscriminatedAssociationAttributeMapping
return 2; return 2;
} }
@Override
public Fetchable getFetchable(int position) {
switch ( position ) {
case 0:
return getDiscriminatorPart();
case 1:
return getKeyPart();
}
throw new IndexOutOfBoundsException(position);
}
@Override @Override
public int getJdbcTypeCount() { public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount(); return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();
@ -313,6 +324,12 @@ public class DiscriminatedAssociationAttributeMapping
fetchableConsumer.accept( getKeyPart() ); fetchableConsumer.accept( getKeyPart() );
} }
@Override
public void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( 0, getDiscriminatorPart() );
fetchableConsumer.accept( 1, getKeyPart() );
}
@Override @Override
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) { public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
return discriminatorMapping.findSubPart( name, treatTargetType ); return discriminatorMapping.findSubPart( name, treatTargetType );

View File

@ -40,6 +40,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.FetchOptions; 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.Fetchable;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -212,6 +213,17 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
return 2; return 2;
} }
@Override
public Fetchable getFetchable(int position) {
switch ( position ) {
case 0:
return getDiscriminatorPart();
case 1:
return getKeyPart();
}
throw new IndexOutOfBoundsException(position);
}
@Override @Override
public int getJdbcTypeCount() { public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount(); return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();

View File

@ -561,11 +561,24 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
return attributeMappings.size(); return attributeMappings.size();
} }
@Override
public Fetchable getFetchable(int position) {
return attributeMappings.get( position );
}
@Override @Override
public void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) { public void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
visitAttributeMappings( fetchableConsumer ); visitAttributeMappings( fetchableConsumer );
} }
@Override
public void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
final int size = attributeMappings.size();
for ( int i = 0; i < size; i++ ) {
fetchableConsumer.accept( i, attributeMappings.get( i ) );
}
}
@Override @Override
public SelectableMapping getSelectable(int columnIndex) { public SelectableMapping getSelectable(int columnIndex) {
return getSelectableMappings().getSelectable( columnIndex ); return getSelectableMappings().getSelectable( columnIndex );
@ -591,33 +604,31 @@ public class EmbeddableMappingTypeImpl extends AbstractEmbeddableMapping impleme
@Override @Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) { public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
final int size = attributeMappings.size();
if ( domainValue instanceof Object[] ) { if ( domainValue instanceof Object[] ) {
final Object[] values = (Object[]) domainValue; final Object[] values = (Object[]) domainValue;
assert values.length == attributeMappings.size(); assert values.length == size;
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = attributeMappings.get( i );
final Object attributeValue = values[ i ]; final Object attributeValue = values[ i ];
attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session ); attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session );
} }
} }
else { else {
attributeMappings.forEach( for ( int i = 0; i < size; i++ ) {
(attributeMapping) -> { final AttributeMapping attributeMapping = attributeMappings.get( i );
final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue ); final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue );
attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session ); attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session );
} }
);
} }
} }
@Override @Override
public Object disassemble(Object value, SharedSessionContractImplementor session) { public Object disassemble(Object value, SharedSessionContractImplementor session) {
final List<AttributeMapping> attributeMappings = getAttributeMappings(); final Object[] result = new Object[ getNumberOfAttributeMappings() ];
for ( int i = 0; i < result.length; i++ ) {
final Object[] result = new Object[ attributeMappings.size() ]; final AttributeMapping attributeMapping = getAttributeMapping( i );
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
result[i] = attributeMapping.disassemble( o, session ); result[i] = attributeMapping.disassemble( o, session );
} }

View File

@ -351,6 +351,11 @@ public class EmbeddedAttributeMapping
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings(); return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
} }
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override @Override
public String toString() { public String toString() {
return "EmbeddedAttributeMapping(" + navigableRole + ")@" + System.identityHashCode( this ); return "EmbeddedAttributeMapping(" + navigableRole + ")@" + System.identityHashCode( this );

View File

@ -49,6 +49,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.FetchOptions; 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.Fetchable;
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl; import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
@ -328,6 +329,11 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings(); return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
} }
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override @Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) { public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, valueConsumer, session ); getEmbeddableTypeDescriptor().breakDownJdbcValues( domainValue, valueConsumer, session );

View File

@ -92,8 +92,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
() -> { () -> {
// todo (6.0) : how to make sure things we need are ready to go? // todo (6.0) : how to make sure things we need are ready to go?
// - e.g., here, we need access to the sub-attributes // - e.g., here, we need access to the sub-attributes
final List<AttributeMapping> subAttributes = targetMappingType.getEmbeddableTypeDescriptor().getAttributeMappings(); if ( targetMappingType.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings() == 0 ) {
if ( subAttributes.isEmpty() ) {
// todo (6.0) : ^^ for now, this is the only way we "know" that the embeddable has not been finalized yet // todo (6.0) : ^^ for now, this is the only way we "know" that the embeddable has not been finalized yet
return false; return false;
} }

View File

@ -20,6 +20,7 @@ import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlSelection; import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/** /**
* Support for {@link jakarta.persistence.EmbeddedId} * Support for {@link jakarta.persistence.EmbeddedId}
@ -115,6 +116,10 @@ public class EmbeddedIdentifierMappingImpl
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings(); return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
} }
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override @Override
public PropertyAccess getPropertyAccess() { public PropertyAccess getPropertyAccess() {

View File

@ -65,6 +65,7 @@ import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchOptions; 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.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.entity.internal.EntityFetchJoinedImpl; import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
@ -579,6 +580,11 @@ public class EntityCollectionPart
return entityMappingType.getNumberOfFetchables(); return entityMappingType.getNumberOfFetchables();
} }
@Override
public Fetchable getFetchable(int position) {
return entityMappingType.getFetchable( position );
}
public String getMappedBy() { public String getMappedBy() {
return collectionDescriptor.getMappedByProperty(); return collectionDescriptor.getMappedByProperty();
} }

View File

@ -45,6 +45,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupProducer; import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -179,15 +180,13 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
session.getSessionFactory() session.getSessionFactory()
); );
final List<AttributeMapping> virtualIdAttribute = virtualIdEmbeddable.getAttributeMappings(); final Object[] propertyValues = new Object[virtualIdEmbeddable.getNumberOfAttributeMappings()];
final List<AttributeMapping> idClassAttribute = getAttributeMappings();
final Object[] propertyValues = new Object[virtualIdAttribute.size()];
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = virtualIdAttribute.get( i ); final AttributeMapping attributeMapping = virtualIdEmbeddable.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttribute.get( i ); final AttributeMapping idClassAttributeMapping = getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue(); propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue();
} }
@ -197,7 +196,7 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
} }
//JPA 2 @MapsId + @IdClass points to the pk of the entity //JPA 2 @MapsId + @IdClass points to the pk of the entity
else if ( attributeMapping instanceof ToOneAttributeMapping else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttribute.get( i ) instanceof ToOneAttributeMapping ) ) { && !( getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart( final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse() toOneAttributeMapping.getSideNature().inverse()
@ -339,6 +338,11 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
return getNumberOfAttributeMappings(); return getNumberOfAttributeMappings();
} }
@Override
public Fetchable getFetchable(int position) {
return attributeMappings.get( position );
}
@Override @Override
public EntityMappingType findContainingEntityMapping() { public EntityMappingType findContainingEntityMapping() {
return idMapping.findContainingEntityMapping(); return idMapping.findContainingEntityMapping();
@ -415,12 +419,10 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
@Override @Override
public Object disassemble(Object value, SharedSessionContractImplementor session) { public Object disassemble(Object value, SharedSessionContractImplementor session) {
final List<AttributeMapping> attributeMappings = getAttributeMappings();
// todo (6.0) : reduce to-one values to id here? // todo (6.0) : reduce to-one values to id here?
final Object[] result = new Object[ attributeMappings.size() ]; final Object[] result = new Object[ getNumberOfAttributeMappings() ];
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < result.length; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = getAttributeMapping( i );
Object o = attributeMapping.getPropertyAccess().getGetter().get( value ); Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
result[i] = attributeMapping.disassemble( o, session ); result[i] = attributeMapping.disassemble( o, session );
} }

View File

@ -36,6 +36,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupProducer; import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/** /**
* The inverse part of a "non-aggregated" composite identifier. * The inverse part of a "non-aggregated" composite identifier.
@ -153,31 +154,31 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
navigablePath, navigablePath,
getContainingTableExpression() getContainingTableExpression()
); );
int offset = 0; identifierValueMapper.forEachSelectable(
for ( AttributeMapping attributeMapping : identifierValueMapper.getAttributeMappings() ) { 0,
offset += attributeMapping.forEachSelectable( (columnIndex, selection) -> {
offset, final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
(columnIndex, selection) -> { ? defaultTableReference
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null : tableGroup.resolveTableReference(
? defaultTableReference navigablePath,
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() ); selection.getContainingTableExpression()
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver() );
.resolveSqlExpression( final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
SqlExpressionResolver.createColumnReferenceKey( .resolveSqlExpression(
tableReference, SqlExpressionResolver.createColumnReferenceKey(
selection.getSelectionExpression() tableReference,
), selection.getSelectionExpression()
sqlAstProcessingState -> new ColumnReference( ),
tableReference.getIdentificationVariable(), sqlAstProcessingState -> new ColumnReference(
selection, tableReference.getIdentificationVariable(),
sqlAstCreationState.getCreationContext().getSessionFactory() selection,
) sqlAstCreationState.getCreationContext().getSessionFactory()
); )
);
columnReferences.add( (ColumnReference) columnReference ); columnReferences.add( (ColumnReference) columnReference );
} }
); );
}
return new SqlTuple( columnReferences, this ); return new SqlTuple( columnReferences, this );
} }
@ -196,14 +197,13 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
null, null,
null//sessionFactory null//sessionFactory
); );
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings(); final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final List<AttributeMapping> idClassAttributeMappings = identifierValueMapper.getAttributeMappings(); final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
final Object[] propertyValues = new Object[attributeMappings.size()];
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttributeMappings.get( i ); final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue(); propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue();
} }
@ -213,7 +213,7 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
} }
//JPA 2 @MapsId + @IdClass points to the pk of the entity //JPA 2 @MapsId + @IdClass points to the pk of the entity
else if ( attributeMapping instanceof ToOneAttributeMapping else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttributeMappings.get( i ) instanceof ToOneAttributeMapping ) ) { && !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart( final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse() toOneAttributeMapping.getSideNature().inverse()
@ -240,39 +240,35 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
@Override @Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) { public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
final List<AttributeMapping> mappedIdAttributeMappings = identifierValueMapper.getAttributeMappings(); final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];
final Object[] propertyValues = new Object[mappedIdAttributeMappings.size()]; final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
for ( int position = 0; position < propertyValues.length; position++ ) {
getEmbeddableTypeDescriptor().forEachAttributeMapping( final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( position );
(position, attribute) -> { final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( position );
final AttributeMapping mappedIdAttributeMapping = mappedIdAttributeMappings.get( position ); Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
final Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id ); if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) { final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute; final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType() .getEntityPersister();
.getEntityPersister(); final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final EntityKey entityKey = session.generateEntityKey( o, entityPersister ); final PersistenceContext persistenceContext = session.getPersistenceContext();
final PersistenceContext persistenceContext = session.getPersistenceContext(); // it is conceivable there is a proxy, so check that first
// it is conceivable there is a proxy, so check that first o = persistenceContext.getProxy( entityKey );
propertyValues[position] = persistenceContext.getProxy( entityKey ); if ( o == null ) {
if ( propertyValues[position] == null ) { // otherwise look for an initialized version
// otherwise look for an initialized version o = persistenceContext.getEntity( entityKey );
propertyValues[position] = persistenceContext.getEntity( entityKey ); if ( o == null ) {
if ( propertyValues[position] == null ) { o = entityDescriptor
propertyValues[position] = entityDescriptor .findAttributeMapping( toOneAttributeMapping.getAttributeName() )
.findAttributeMapping( toOneAttributeMapping.getAttributeName() ) .getPropertyAccess()
.getPropertyAccess() .getGetter()
.getGetter() .get( entity );
.get( entity );
}
}
}
else {
propertyValues[position] = o;
} }
} }
); }
getEmbeddableTypeDescriptor().setValues( entity, propertyValues ); propertyValues[position] = o;
}
embeddableTypeDescriptor.setValues( entity, propertyValues );
} }
@Override @Override
@ -313,6 +309,11 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
@Override @Override
public int getNumberOfFetchables() { public int getNumberOfFetchables() {
return identifierValueMapper.getNumberOfFetchables(); return getPartMappingType().getNumberOfFetchables();
}
@Override
public Fetchable getFetchable(int position) {
return getPartMappingType().getFetchable( position );
} }
} }

View File

@ -36,6 +36,7 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
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;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/** /**
* A "non-aggregated" composite identifier. * A "non-aggregated" composite identifier.
@ -179,31 +180,31 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
navigablePath, navigablePath,
getContainingTableExpression() getContainingTableExpression()
); );
int offset = 0; identifierValueMapper.forEachSelectable(
for ( AttributeMapping attributeMapping : identifierValueMapper.getAttributeMappings() ) { 0,
offset += attributeMapping.forEachSelectable( (columnIndex, selection) -> {
offset, final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
(columnIndex, selection) -> { ? defaultTableReference
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null : tableGroup.resolveTableReference(
? defaultTableReference navigablePath,
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() ); selection.getContainingTableExpression()
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver() );
.resolveSqlExpression( final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
SqlExpressionResolver.createColumnReferenceKey( .resolveSqlExpression(
tableReference, SqlExpressionResolver.createColumnReferenceKey(
selection.getSelectionExpression() tableReference,
), selection.getSelectionExpression()
sqlAstProcessingState -> new ColumnReference( ),
tableReference.getIdentificationVariable(), sqlAstProcessingState -> new ColumnReference(
selection, tableReference.getIdentificationVariable(),
sqlAstCreationState.getCreationContext().getSessionFactory() selection,
) sqlAstCreationState.getCreationContext().getSessionFactory()
); )
);
columnReferences.add( (ColumnReference) columnReference ); columnReferences.add( (ColumnReference) columnReference );
} }
); );
}
return new SqlTuple( columnReferences, this ); return new SqlTuple( columnReferences, this );
} }
@ -222,14 +223,13 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
null, null,
sessionFactory sessionFactory
); );
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings(); final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final List<AttributeMapping> idClassAttributeMappings = identifierValueMapper.getAttributeMappings(); final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
final Object[] propertyValues = new Object[attributeMappings.size()];
for ( int i = 0; i < propertyValues.length; i++ ) { for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity ); final Object o = attributeMapping.getPropertyAccess().getGetter().get( entity );
if ( o == null ) { if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttributeMappings.get( i ); final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) { if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue(); propertyValues[i] = idClassAttributeMapping.getExpressibleJavaType().getDefaultValue();
} }
@ -239,7 +239,7 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
} }
//JPA 2 @MapsId + @IdClass points to the pk of the entity //JPA 2 @MapsId + @IdClass points to the pk of the entity
else if ( attributeMapping instanceof ToOneAttributeMapping else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttributeMappings.get( i ) instanceof ToOneAttributeMapping ) ) { && !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping; final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart( final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse() toOneAttributeMapping.getSideNature().inverse()
@ -266,39 +266,35 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
@Override @Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) { public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
final List<AttributeMapping> mappedIdAttributeMappings = identifierValueMapper.getAttributeMappings(); final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];
final Object[] propertyValues = new Object[mappedIdAttributeMappings.size()]; final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
for ( int i = 0; i < propertyValues.length; i++ ) {
getEmbeddableTypeDescriptor().forEachAttributeMapping( final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( i );
(position, attribute) -> { final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( i );
final AttributeMapping mappedIdAttributeMapping = mappedIdAttributeMappings.get( position ); Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
final Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id ); if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) { final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute; final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType() .getEntityPersister();
.getEntityPersister(); final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final EntityKey entityKey = session.generateEntityKey( o, entityPersister ); final PersistenceContext persistenceContext = session.getPersistenceContext();
final PersistenceContext persistenceContext = session.getPersistenceContext(); // it is conceivable there is a proxy, so check that first
// it is conceivable there is a proxy, so check that first o = persistenceContext.getProxy( entityKey );
propertyValues[position] = persistenceContext.getProxy( entityKey ); if ( o == null ) {
if ( propertyValues[position] == null ) { // otherwise look for an initialized version
// otherwise look for an initialized version o = persistenceContext.getEntity( entityKey );
propertyValues[position] = persistenceContext.getEntity( entityKey ); if ( o == null ) {
if ( propertyValues[position] == null ) { // get the association out of the entity itself
// get the association out of the entity itself o = entityDescriptor.getPropertyValue(
propertyValues[position] = entityDescriptor.getPropertyValue( entity,
entity, toOneAttributeMapping.getAttributeName()
toOneAttributeMapping.getAttributeName() );
);
}
}
}
else {
propertyValues[position] = o;
} }
} }
); }
getEmbeddableTypeDescriptor().setValues( entity, propertyValues ); propertyValues[i] = o;
}
embeddableTypeDescriptor.setValues( entity, propertyValues );
} }
@Override @Override
@ -339,6 +335,11 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
@Override @Override
public int getNumberOfFetchables() { public int getNumberOfFetchables() {
return identifierValueMapper.getNumberOfFetchables(); return getPartMappingType().getNumberOfFetchables();
}
@Override
public Fetchable getFetchable(int position) {
return getPartMappingType().getFetchable( position );
} }
} }

View File

@ -926,11 +926,6 @@ public class PluralAttributeMappingImpl
return elementDescriptor.forEachDisassembledJdbcValue( value, clause, offset, valuesConsumer, session ); return elementDescriptor.forEachDisassembledJdbcValue( value, clause, offset, valuesConsumer, session );
} }
@Override
public int getNumberOfFetchables() {
return indexDescriptor == null ? 1 : 2;
}
@Override @Override
public String toString() { public String toString() {
return "PluralAttribute(" + getCollectionDescriptor().getRole() + ")"; return "PluralAttribute(" + getCollectionDescriptor().getRole() + ")";

View File

@ -82,6 +82,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.FetchOptions; 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.Fetchable;
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
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;
@ -1546,6 +1547,11 @@ public class ToOneAttributeMapping
return getEntityMappingType().getNumberOfFetchables(); return getEntityMappingType().getNumberOfFetchables();
} }
@Override
public Fetchable getFetchable(int position) {
return getEntityMappingType().getFetchable( position );
}
@Override @Override
public TableGroupJoin createTableGroupJoin( public TableGroupJoin createTableGroupJoin(
NavigablePath navigablePath, NavigablePath navigablePath,

View File

@ -33,6 +33,7 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupProducer; import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType; import org.hibernate.type.CompositeType;
@ -257,6 +258,11 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
return getNumberOfAttributeMappings(); return getNumberOfAttributeMappings();
} }
@Override
public Fetchable getFetchable(int position) {
return attributeMappings.get( position );
}
@Override @Override
public EntityMappingType findContainingEntityMapping() { public EntityMappingType findContainingEntityMapping() {
return idMapping.findContainingEntityMapping(); return idMapping.findContainingEntityMapping();

View File

@ -247,6 +247,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.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.internal.SqlSelectionImpl; import org.hibernate.sql.results.internal.SqlSelectionImpl;
@ -1970,55 +1971,56 @@ public abstract class AbstractEntityPersister
} }
private List<Fetch> fetchProcessor(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) { private List<Fetch> fetchProcessor(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) {
final List<Fetch> fetches = new ArrayList<>(); final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
final String rootTableName = getRootTableName(); final int size = fetchableContainer.getNumberOfFetchables();
fetchParent.getReferencedMappingContainer().visitFetchables( final List<Fetch> fetches = new ArrayList<>( size );
fetchable -> {
// Ignore plural attributes
if ( !(fetchable instanceof PluralAttributeMapping ) ) {
final FetchTiming fetchTiming;
if ( fetchable instanceof BasicValuedModelPart ) {
// Ignore lazy basic columns
fetchTiming = fetchable.getMappedFetchOptions().getTiming();
if ( fetchTiming == FetchTiming.DELAYED ) {
return;
}
}
else if ( fetchable instanceof Association ) {
final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
if ( association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {
return;
}
// Ensure the FK comes from the root table
if ( !rootTableName.equals( association.getForeignKeyDescriptor().getKeyTable() ) ) {
return;
}
fetchTiming = FetchTiming.DELAYED;
}
else {
fetchTiming = fetchable.getMappedFetchOptions().getTiming();
}
if ( fetchTiming == null ) { for ( int i = 0; i < size; i++ ) {
throw new AssertionFailure("fetchTiming was null"); final Fetchable fetchable = fetchableContainer.getFetchable( i );
} // Ignore plural attributes
if ( !( fetchable instanceof PluralAttributeMapping ) ) {
if ( isSelectable( fetchParent, fetchable ) ) { final FetchTiming fetchTiming;
final Fetch fetch = fetchParent.generateFetchableFetch( if ( fetchable instanceof BasicValuedModelPart ) {
fetchable, // Ignore lazy basic columns
fetchParent.resolveNavigablePath( fetchable ), fetchTiming = fetchable.getMappedFetchOptions().getTiming();
fetchTiming, if ( fetchTiming == FetchTiming.DELAYED ) {
true, continue;
null,
creationState
);
fetches.add( fetch );
}
} }
}, }
null else if ( fetchable instanceof Association ) {
); final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
if ( association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {
continue;
}
// Ensure the FK comes from the root table
if ( !getRootTableName().equals( association.getForeignKeyDescriptor().getKeyTable() ) ) {
continue;
}
fetchTiming = FetchTiming.DELAYED;
}
else {
fetchTiming = fetchable.getMappedFetchOptions().getTiming();
}
if ( fetchTiming == null ) {
throw new AssertionFailure("fetchTiming was null");
}
if ( isSelectable( fetchParent, fetchable ) ) {
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
fetchParent.resolveNavigablePath( fetchable ),
fetchTiming,
true,
null,
creationState
);
fetches.add( fetch );
}
}
}
return fetches; return fetches;
} }
@ -5084,31 +5086,23 @@ public abstract class AbstractEntityPersister
} }
else { else {
if ( hasSubclasses() ) { if ( hasSubclasses() ) {
visitAttributeMappings( for ( int i = 0; i < attributeMappings.size(); i++ ) {
attribute -> { final Object value = values[i];
final int stateArrayPosition = attribute.getStateArrayPosition(); if ( value != UNFETCHED_PROPERTY ) {
final Object value = values[stateArrayPosition]; final Setter setter = attributeMappings.get( i ).getPropertyAccess().getSetter();
if ( value != UNFETCHED_PROPERTY ) { setter.set( object, value );
final Setter setter = attribute.getPropertyAccess().getSetter(); }
setter.set( object, value ); }
}
}
);
} }
else { else {
visitFetchables( for ( int i = 0; i < staticFetchableList.size(); i++ ) {
fetchable -> { final AttributeMapping attribute = (AttributeMapping) staticFetchableList.get( i );
final AttributeMapping attribute = (AttributeMapping) fetchable; final Object value = values[i];
final int stateArrayPosition = attribute.getStateArrayPosition(); if ( value != UNFETCHED_PROPERTY ) {
final Object value = values[stateArrayPosition]; final Setter setter = attribute.getPropertyAccess().getSetter();
if ( value != UNFETCHED_PROPERTY ) { setter.set( object, value );
final Setter setter = attribute.getPropertyAccess().getSetter(); }
setter.set( object, value ); }
}
},
null
);
} }
} }
} }
@ -6101,7 +6095,7 @@ public abstract class AbstractEntityPersister
@Override @Override
public void visitDeclaredAttributeMappings(Consumer<? super AttributeMapping> action) { public void visitDeclaredAttributeMappings(Consumer<? super AttributeMapping> action) {
declaredAttributeMappings.forEach( (key,value) -> action.accept( value ) ); declaredAttributeMappings.values().forEach( action );
} }
@Override @Override
@ -6700,22 +6694,33 @@ public abstract class AbstractEntityPersister
} }
@Override @Override
public void visitKeyFetchables( public void visitKeyFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
Consumer<Fetchable> fetchableConsumer, // No-op
EntityMappingType treatTargetType) { }
// final EntityIdentifierMapping identifierMapping = getIdentifierMapping();
// if ( identifierMapping instanceof FetchableContainer ) { @Override
// // essentially means the entity has a composite id - ask the embeddable to visit its fetchables public void visitKeyFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
// ( (FetchableContainer) identifierMapping ).visitFetchables( fetchableConsumer, treatTargetType ); // No-op
// }
// else {
// fetchableConsumer.accept( (Fetchable) identifierMapping );
// }
} }
@Override @Override
public int getNumberOfFetchables() { public int getNumberOfFetchables() {
return attributeMappings.size(); return getStaticFetchableList().size();
}
@Override
public int getNumberOfKeyFetchables() {
return 0;
}
@Override
public Fetchable getKeyFetchable(int position) {
throw new IndexOutOfBoundsException( position );
}
@Override
public Fetchable getFetchable(int position) {
return getStaticFetchableList().get( position );
} }
@Override @Override
@ -6737,6 +6742,35 @@ public abstract class AbstractEntityPersister
} }
} }
@Override
public void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
if ( treatTargetType == null ) {
final List<Fetchable> fetchableList = getStaticFetchableList();
final int size = fetchableList.size();
for ( int i = 0; i < size; i++ ) {
fetchableConsumer.accept( i, fetchableList.get( i ) );
}
// EARLY EXIT!!!
return;
}
final int size = attributeMappings.size();
for ( int i = 0; i < size; i++ ) {
fetchableConsumer.accept( i, attributeMappings.get( i ) );
}
if ( treatTargetType.isTypeOrSuperType( this ) ) {
if ( subclassMappingTypes != null ) {
int offset = size;
for ( EntityMappingType subtype : subclassMappingTypes.values() ) {
final Collection<AttributeMapping> declaredAttributeMappings = subtype.getDeclaredAttributeMappings();
for ( AttributeMapping declaredAttributeMapping : declaredAttributeMappings ) {
fetchableConsumer.accept( offset++, declaredAttributeMapping );
}
}
}
}
}
protected List<Fetchable> getStaticFetchableList() { protected List<Fetchable> getStaticFetchableList() {
return staticFetchableList; return staticFetchableList;
} }
@ -6769,7 +6803,9 @@ public abstract class AbstractEntityPersister
public void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) { public void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
visitAttributeMappings( action ); visitAttributeMappings( action );
if ( subclassMappingTypes != null ) { if ( subclassMappingTypes != null ) {
subclassMappingTypes.forEach( (s, subType) -> subType.visitDeclaredAttributeMappings( action ) ); for ( EntityMappingType subType : subclassMappingTypes.values() ) {
subType.visitDeclaredAttributeMappings( action );
}
} }
} }

View File

@ -462,17 +462,16 @@ public interface EntityPersister
@Override @Override
default void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) { default void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
final List<AttributeMapping> attributeMappings = getAttributeMappings();
if ( domainValue instanceof Object[] ) { if ( domainValue instanceof Object[] ) {
final Object[] values = (Object[]) domainValue; final Object[] values = (Object[]) domainValue;
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = getAttributeMapping( i );
attributeMapping.breakDownJdbcValues( values[ i ], valueConsumer, session ); attributeMapping.breakDownJdbcValues( values[ i ], valueConsumer, session );
} }
} }
else { else {
for ( int i = 0; i < attributeMappings.size(); i++ ) { for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i ); final AttributeMapping attributeMapping = getAttributeMapping( i );
final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue ); final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue );
attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session ); attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session );
} }

View File

@ -6,26 +6,31 @@
*/ */
package org.hibernate.query.results.implicit; package org.hibernate.query.results.implicit;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.results.Builders; import org.hibernate.query.results.Builders;
import org.hibernate.query.results.DomainResultCreationStateImpl; import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder; import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy; import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
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.Fetchable;
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -48,24 +53,22 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
final DomainResultCreationStateImpl creationStateImpl = impl( creationState ); final DomainResultCreationStateImpl creationStateImpl = impl( creationState );
final NavigablePath relativePath = creationStateImpl.getCurrentRelativePath(); final NavigablePath relativePath = creationStateImpl.getCurrentRelativePath();
final Function<String, FetchBuilder> fetchBuilderResolver = creationStateImpl.getCurrentExplicitFetchMementoResolver(); final Function<String, FetchBuilder> fetchBuilderResolver = creationStateImpl.getCurrentExplicitFetchMementoResolver();
final Map<NavigablePath, FetchBuilder> fetchBuilders = new LinkedHashMap<>( fetchable.getNumberOfFetchables() ); final int size = fetchable.getNumberOfFetchables();
fetchable.visitFetchables( final Map<NavigablePath, FetchBuilder> fetchBuilders = CollectionHelper.linkedMapOfSize( size );
subFetchable -> { for ( int i = 0; i < size; i++ ) {
final NavigablePath subFetchPath = relativePath.append( subFetchable.getFetchableName() ); final Fetchable subFetchable = fetchable.getFetchable( i );
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver final NavigablePath subFetchPath = relativePath.append( subFetchable.getFetchableName() );
.apply( subFetchPath.getFullPath() ); final FetchBuilder explicitFetchBuilder = fetchBuilderResolver.apply( subFetchPath.getFullPath() );
if ( explicitFetchBuilder == null ) { if ( explicitFetchBuilder == null ) {
fetchBuilders.put( fetchBuilders.put(
subFetchPath, subFetchPath,
Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl ) Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl )
); );
} }
else { else {
fetchBuilders.put( subFetchPath, explicitFetchBuilder ); fetchBuilders.put( subFetchPath, explicitFetchBuilder );
} }
}, }
null
);
this.fetchBuilders = fetchBuilders; this.fetchBuilders = fetchBuilders;
} }

View File

@ -15,6 +15,7 @@ import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
@ -27,6 +28,7 @@ import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
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.Fetchable;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.query.results.ResultsHelper.impl; import static org.hibernate.query.results.ResultsHelper.impl;
@ -70,24 +72,22 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder {
final MappingType partMappingType = foreignKeyDescriptor.getPartMappingType(); final MappingType partMappingType = foreignKeyDescriptor.getPartMappingType();
if ( partMappingType instanceof EmbeddableMappingType ) { if ( partMappingType instanceof EmbeddableMappingType ) {
final EmbeddableMappingType embeddableValuedModelPart = (EmbeddableMappingType) partMappingType; final EmbeddableMappingType embeddableValuedModelPart = (EmbeddableMappingType) partMappingType;
fetchBuilders = new LinkedHashMap<>( embeddableValuedModelPart.getNumberOfFetchables() ); final int size = embeddableValuedModelPart.getNumberOfFetchables();
embeddableValuedModelPart.visitFetchables( fetchBuilders = CollectionHelper.linkedMapOfSize( size );
subFetchable -> { for ( int i = 0; i < size; i++ ) {
final NavigablePath subFetchPath = associationKeyFetchPath.append( subFetchable.getFetchableName() ); final Fetchable subFetchable = embeddableValuedModelPart.getFetchable( i );
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver final NavigablePath subFetchPath = associationKeyFetchPath.append( subFetchable.getFetchableName() );
.apply( subFetchPath.getFullPath() ); final FetchBuilder explicitFetchBuilder = fetchBuilderResolver.apply( subFetchPath.getFullPath() );
if ( explicitFetchBuilder == null ) { if ( explicitFetchBuilder == null ) {
fetchBuilders.put( fetchBuilders.put(
subFetchPath, subFetchPath,
Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl ) Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl )
); );
} }
else { else {
fetchBuilders.put( subFetchPath, explicitFetchBuilder ); fetchBuilders.put( subFetchPath, explicitFetchBuilder );
} }
}, }
null
);
} }
else { else {
fetchBuilders = Collections.emptyMap(); fetchBuilders = Collections.emptyMap();

View File

@ -374,6 +374,7 @@ import org.hibernate.sql.results.graph.EntityGraphTraversalState;
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.FetchableContainer;
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation; import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation;
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;
@ -5356,7 +5357,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
else { else {
for ( int i = 0; i < size; i++ ) { for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMappings().get( i ); final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
inferrableTypeAccessStack.push( () -> attributeMapping ); inferrableTypeAccessStack.push( () -> attributeMapping );
try { try {
expressions.add( (Expression) groupedExpressions.get( i ).accept( this ) ); expressions.add( (Expression) groupedExpressions.get( i ).accept( this ) );
@ -7092,10 +7093,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override @Override
public List<Fetch> visitFetches(FetchParent fetchParent) { public List<Fetch> visitFetches(FetchParent fetchParent) {
final List<Fetch> fetches = CollectionHelper.arrayList( fetchParent.getReferencedMappingType().getNumberOfFetchables() ); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
final int keySize = referencedMappingContainer.getNumberOfKeyFetchables();
fetchParent.getReferencedMappingContainer().visitKeyFetchables( fetchable -> addFetch( fetches, fetchParent, fetchable, true ), null ); final int size = referencedMappingContainer.getNumberOfFetchables();
fetchParent.getReferencedMappingContainer().visitFetchables( fetchable -> addFetch( fetches, fetchParent, fetchable, false ), null ); final List<Fetch> fetches = CollectionHelper.arrayList( keySize + size );
for ( int i = 0; i < keySize; i++ ) {
addFetch( fetches, fetchParent, referencedMappingContainer.getKeyFetchable( i ), true );
}
for ( int i = 0; i < size; i++ ) {
addFetch( fetches, fetchParent, referencedMappingContainer.getFetchable( i ), false );
}
return fetches; return fetches;
} }

View File

@ -6,8 +6,12 @@
*/ */
package org.hibernate.sql.results.graph; package org.hibernate.sql.results.graph;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.hibernate.internal.util.MutableInteger;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
@ -17,21 +21,71 @@ import org.hibernate.metamodel.mapping.ModelPartContainer;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface FetchableContainer extends ModelPartContainer { public interface FetchableContainer extends ModelPartContainer {
/**
* The number of key fetchables in the container
*/
default int getNumberOfKeyFetchables() {
return 0;
}
/** /**
* The number of fetchables in the container * The number of fetchables in the container
*/ */
int getNumberOfFetchables(); int getNumberOfFetchables();
default Fetchable getKeyFetchable(int position) {
List<Fetchable> fetchables = new ArrayList<>( getNumberOfKeyFetchables() );
visitKeyFetchables( fetchable -> fetchables.add( fetchable ), null );
return fetchables.get( position );
}
default Fetchable getFetchable(int position) {
List<Fetchable> fetchables = new ArrayList<>( getNumberOfFetchables() );
visitFetchables( fetchable -> fetchables.add( fetchable ), null );
return fetchables.get( position );
}
default void visitKeyFetchables( default void visitKeyFetchables(
Consumer<Fetchable> fetchableConsumer, Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) { EntityMappingType treatTargetType) {
// by default, nothing to do // by default, nothing to do
} }
default void visitKeyFetchables(
IndexedConsumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
visitKeyFetchables( 0, fetchableConsumer, treatTargetType );
}
default void visitKeyFetchables(
int offset,
IndexedConsumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
// by default, nothing to do
}
default void visitFetchables( default void visitFetchables(
Consumer<Fetchable> fetchableConsumer, Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) { EntityMappingType treatTargetType) {
//noinspection unchecked //noinspection unchecked
visitSubParts( (Consumer) fetchableConsumer, treatTargetType ); visitSubParts( (Consumer) fetchableConsumer, treatTargetType );
} }
default void visitFetchables(
IndexedConsumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
visitFetchables( 0, fetchableConsumer, treatTargetType );
}
default void visitFetchables(
int offset,
IndexedConsumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
final MutableInteger index = new MutableInteger( offset );
visitSubParts(
modelPart -> fetchableConsumer.accept( index.getAndIncrement(), (Fetchable) modelPart ),
treatTargetType
);
}
} }

View File

@ -31,6 +31,7 @@ import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
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.Initializer; import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer;
@ -90,22 +91,19 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
this.representationStrategy = representationEmbeddable.getRepresentationStrategy(); this.representationStrategy = representationEmbeddable.getRepresentationStrategy();
this.usesStandardInstantiation = representationStrategy.getInstantiator() instanceof StandardEmbeddableInstantiator; this.usesStandardInstantiation = representationStrategy.getInstantiator() instanceof StandardEmbeddableInstantiator;
final int numOfAttrs = embeddableTypeDescriptor.getNumberOfAttributeMappings(); final int size = embeddableTypeDescriptor.getNumberOfFetchables();
this.rowState = new Object[ numOfAttrs ]; this.rowState = new Object[ size ];
this.assemblers = arrayList( numOfAttrs ); this.assemblers = arrayList( size );
for ( int i = 0; i < size; i++ ) {
final Fetchable stateArrayContributor = embeddableTypeDescriptor.getFetchable( i );
final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor );
embeddableTypeDescriptor.visitFetchables( final DomainResultAssembler<?> stateAssembler = fetch == null
stateArrayContributor -> { ? new NullValueAssembler<>( stateArrayContributor.getJavaType() )
final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor ); : fetch.createAssembler( this, creationState );
final DomainResultAssembler<?> stateAssembler = fetch == null assemblers.add( stateAssembler );
? new NullValueAssembler<>( stateArrayContributor.getJavaType() ) }
: fetch.createAssembler( this, creationState );
assemblers.add( stateAssembler );
},
null
);
// We never want to create empty composites for the FK target or PK, otherwise collections would break // We never want to create empty composites for the FK target or PK, otherwise collections would break
createEmptyCompositesEnabled = !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() ) createEmptyCompositesEnabled = !ForeignKeyDescriptor.PART_NAME.equals( navigablePath.getLocalName() )

View File

@ -34,6 +34,7 @@ import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.NullnessHelper; import org.hibernate.internal.util.NullnessHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.entity.CacheEntityLoaderHelper; import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
@ -165,32 +166,29 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
this.rowIdAssembler = null; this.rowIdAssembler = null;
} }
assemblerMap = new IdentityHashMap<>( entityDescriptor.getNumberOfAttributeMappings() ); final int size = entityDescriptor.getNumberOfFetchables();
assemblerMap = new IdentityHashMap<>( CollectionHelper.determineProperSizing( size ) );
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = (AttributeMapping) entityDescriptor.getFetchable( i );
entityDescriptor.visitFetchables( // todo (6.0) : somehow we need to track whether all state is loaded/resolved
fetchable -> { // note that lazy proxies or uninitialized collections count against
final AttributeMapping attributeMapping = (AttributeMapping) fetchable; // that in the affirmative
// todo (6.0) : somehow we need to track whether all state is loaded/resolved final Fetch fetch = resultDescriptor.findFetch( attributeMapping );
// note that lazy proxies or uninitialized collections count against
// that in the affirmative
final Fetch fetch = resultDescriptor.findFetch( fetchable ); final DomainResultAssembler<?> stateAssembler;
if ( fetch == null ) {
stateAssembler = new NullValueAssembler<>(
attributeMapping.getMappedType().getMappedJavaType()
);
}
else {
stateAssembler = fetch.createAssembler( this, creationState );
}
final DomainResultAssembler<?> stateAssembler; assemblerMap.put( attributeMapping, stateAssembler );
if ( fetch == null ) { }
stateAssembler = new NullValueAssembler<>(
attributeMapping.getMappedType().getMappedJavaType()
);
}
else {
stateAssembler = fetch.createAssembler( this, creationState );
}
assemblerMap.put( attributeMapping, stateAssembler );
},
null
);
} }
private static void deepCopy( private static void deepCopy(

View File

@ -34,7 +34,7 @@ public class EmbeddedComponentType extends ComponentType {
} }
final EmbeddableMappingType embeddable = mappingModelPart().getEmbeddableTypeDescriptor(); final EmbeddableMappingType embeddable = mappingModelPart().getEmbeddableTypeDescriptor();
for ( int i = 0; i < embeddable.getAttributeMappings().size(); i++ ) { for ( int i = 0; i < embeddable.getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = embeddable.getAttributeMapping( i ); final AttributeMapping attributeMapping = embeddable.getAttributeMapping( i );
final Getter getter = attributeMapping.getPropertyAccess().getGetter(); final Getter getter = attributeMapping.getPropertyAccess().getGetter();
final Method getterMethod = getter.getMethod(); final Method getterMethod = getter.getMethod();