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 ) {
// here is the replaying of the explicitly set values we prepared above
for ( String writtenFieldName : writtenFieldNames ) {
List<AttributeMapping> attributeMappings = entityPersister.getAttributeMappings();
for ( int index = 0; index < attributeMappings.size(); index++ ) {
if ( writtenFieldName.contains( attributeMappings.get( index ).getAttributeName() ) ) {
final int size = entityPersister.getNumberOfAttributeMappings();
for ( int index = 0; index < size; index++ ) {
if ( writtenFieldName.contains( entityPersister.getAttributeMapping( index ).getAttributeName() ) ) {
entityPersister.setValue(
target,
index,

View File

@ -30,6 +30,7 @@ import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.loader.entity.CacheEntityLoaderHelper.PersistenceContextEntry;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.MappingType;
@ -118,9 +119,9 @@ public class DefaultLoadEventListener implements LoadEventListener {
final EntityIdentifierMapping idMapping = persister.getIdentifierMapping();
if ( idMapping instanceof CompositeIdentifierMapping ) {
final CompositeIdentifierMapping compositeIdMapping = (CompositeIdentifierMapping) idMapping;
final List<AttributeMapping> attributeMappings = compositeIdMapping.getPartMappingType().getAttributeMappings();
if ( attributeMappings.size() == 1 ) {
final AttributeMapping singleIdAttribute = attributeMappings.get( 0 );
final EmbeddableMappingType partMappingType = compositeIdMapping.getPartMappingType();
if ( partMappingType.getNumberOfAttributeMappings() == 1 ) {
final AttributeMapping singleIdAttribute = partMappingType.getAttributeMapping( 0 );
if ( singleIdAttribute.getMappedType() instanceof EntityMappingType ) {
final EntityMappingType parentIdTargetMapping = (EntityMappingType) singleIdAttribute.getMappedType();
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.results.graph.DomainResult;
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.stat.spi.StatisticsImplementor;
@ -99,25 +102,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
null,
creationState
),
(fetchParent, querySpec, creationState) -> {
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;
},
AbstractNaturalIdLoader::visitFetches,
(statsEnabled) -> {
// entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE );
return statsEnabled ? System.nanoTime() : -1;
@ -326,27 +311,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
null,
creationState
),
(fetchParent, querySpec, creationState) -> {
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;
},
AbstractNaturalIdLoader::visitFetches,
(statsEnabled) -> {
// entityDescriptor().getPreLoadListener().startingLoad( entityDescriptor, naturalIdValue, KeyType.NATURAL_ID, LoadSource.DATABASE );
return statsEnabled ? System.nanoTime() : -1L;
@ -455,4 +420,27 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
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();
if ( fetchParent.getNavigablePath().getParent() != null ) {
referencedMappingContainer.visitKeyFetchables(
fetchable -> processor.accept( fetchable, true ), null );
final int size = referencedMappingContainer.getNumberOfKeyFetchables();
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;
}

View File

@ -194,9 +194,10 @@ public abstract class AbstractCompositeIdentifierMapping
JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session) {
int span = 0;
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings();
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final int size = embeddableTypeDescriptor.getNumberOfAttributeMappings();
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableTypeDescriptor.getAttributeMapping( i );
final Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
if ( attributeMapping instanceof ToOneAttributeMapping ) {
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.DomainResultAssembler;
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.type.descriptor.java.JavaType;
@ -466,6 +467,11 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
return getEntityPersister().getNumberOfFetchables();
}
@Override
default Fetchable getFetchable(int position) {
return getEntityPersister().getFetchable( position );
}
@Override
default void applyDiscriminator(
Consumer<Predicate> predicateConsumer,

View File

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

View File

@ -12,6 +12,7 @@ import java.util.function.Consumer;
import org.hibernate.Filter;
import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
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
default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
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" })
@Override
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.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SortSpecification;
import org.hibernate.sql.results.graph.Fetchable;
/**
* @author Andrea Boriero
@ -86,13 +87,12 @@ public abstract class AbstractDomainPath implements DomainPath {
final EmbeddableValuedModelPart embeddableValuedModelPart = (EmbeddableValuedModelPart) referenceModelPart;
if ( embeddableValuedModelPart.getFetchableName()
.equals( modelPartName ) || ELEMENT_TOKEN.equals( modelPartName ) ) {
final List<Expression> expressions = new ArrayList<>( embeddableValuedModelPart.getNumberOfFetchables() );
embeddableValuedModelPart.visitFetchables(
fetchable -> {
expressions.add( resolve( fetchable, ast, tableGroup, modelPartName, creationState ) );
},
null
);
final int size = embeddableValuedModelPart.getNumberOfFetchables();
final List<Expression> expressions = new ArrayList<>( size );
for ( int i = 0; i < size; i++ ) {
final Fetchable fetchable = embeddableValuedModelPart.getFetchable( i );
expressions.add( resolve( fetchable, ast, tableGroup, modelPartName, creationState ) );
}
return new SqlTuple( expressions, embeddableValuedModelPart );
}
else {

View File

@ -136,7 +136,8 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
MappingModelCreationProcess creationProcess,
ManagedMappingType declaringType,
List<? extends AttributeMapping> attributeMappings) {
if ( inverseMappingType.getAttributeMappings().isEmpty() ) {
final int size = inverseMappingType.getNumberOfAttributeMappings();
if ( size == 0 ) {
return false;
}
//noinspection unchecked
@ -145,7 +146,8 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
mappings.clear();
int currentIndex = 0;
// 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 ) {
final BasicAttributeMapping original = (BasicAttributeMapping) attributeMapping;
final SelectableMapping selectableMapping = selectableMappings.getSelectable( currentIndex );
@ -161,7 +163,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
else if ( attributeMapping instanceof ToOneAttributeMapping ) {
final ToOneAttributeMapping original = (ToOneAttributeMapping) attributeMapping;
ForeignKeyDescriptor foreignKeyDescriptor = original.getForeignKeyDescriptor();
if ( foreignKeyDescriptor==null ) {
if ( foreignKeyDescriptor == null ) {
// This is expected to happen when processing a
// PostInitCallbackEntry because the callbacks
// are not ordered. The exception is caught in
@ -191,7 +193,7 @@ public abstract class AbstractEmbeddableMapping implements EmbeddableMappingType
}
else if ( attributeMapping instanceof EmbeddableValuedModelPart ) {
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++ );
}
attributeMapping = MappingModelCreationHelper.createInverseModelPart(

View File

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

View File

@ -184,6 +184,17 @@ public class DiscriminatedAssociationAttributeMapping
return 2;
}
@Override
public Fetchable getFetchable(int position) {
switch ( position ) {
case 0:
return getDiscriminatorPart();
case 1:
return getKeyPart();
}
throw new IndexOutOfBoundsException(position);
}
@Override
public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();
@ -313,6 +324,12 @@ public class DiscriminatedAssociationAttributeMapping
fetchableConsumer.accept( getKeyPart() );
}
@Override
public void visitFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
fetchableConsumer.accept( 0, getDiscriminatorPart() );
fetchableConsumer.accept( 1, getKeyPart() );
}
@Override
public ModelPart findSubPart(String name, EntityMappingType 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.FetchOptions;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType;
import org.hibernate.type.descriptor.java.JavaType;
@ -212,6 +213,17 @@ public class DiscriminatedCollectionPart implements DiscriminatedAssociationMode
return 2;
}
@Override
public Fetchable getFetchable(int position) {
switch ( position ) {
case 0:
return getDiscriminatorPart();
case 1:
return getKeyPart();
}
throw new IndexOutOfBoundsException(position);
}
@Override
public int getJdbcTypeCount() {
return getDiscriminatorPart().getJdbcTypeCount() + getKeyPart().getJdbcTypeCount();

View File

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

View File

@ -351,6 +351,11 @@ public class EmbeddedAttributeMapping
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
public String toString() {
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.FetchOptions;
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.internal.EmbeddableFetchImpl;
import org.hibernate.sql.results.graph.embeddable.internal.EmbeddableResultImpl;
@ -328,6 +329,11 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor 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?
// - e.g., here, we need access to the sub-attributes
final List<AttributeMapping> subAttributes = targetMappingType.getEmbeddableTypeDescriptor().getAttributeMappings();
if ( subAttributes.isEmpty() ) {
if ( targetMappingType.getEmbeddableTypeDescriptor().getNumberOfAttributeMappings() == 0 ) {
// todo (6.0) : ^^ for now, this is the only way we "know" that the embeddable has not been finalized yet
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.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/**
* Support for {@link jakarta.persistence.EmbeddedId}
@ -115,6 +116,10 @@ public class EmbeddedIdentifierMappingImpl
return getEmbeddableTypeDescriptor().getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return getEmbeddableTypeDescriptor().getFetchable( position );
}
@Override
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.FetchOptions;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
import org.hibernate.sql.results.graph.entity.internal.EntityFetchJoinedImpl;
@ -579,6 +580,11 @@ public class EntityCollectionPart
return entityMappingType.getNumberOfFetchables();
}
@Override
public Fetchable getFetchable(int position) {
return entityMappingType.getFetchable( position );
}
public String getMappedBy() {
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.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
@ -179,15 +180,13 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
session.getSessionFactory()
);
final List<AttributeMapping> virtualIdAttribute = virtualIdEmbeddable.getAttributeMappings();
final List<AttributeMapping> idClassAttribute = getAttributeMappings();
final Object[] propertyValues = new Object[virtualIdAttribute.size()];
final Object[] propertyValues = new Object[virtualIdEmbeddable.getNumberOfAttributeMappings()];
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 );
if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttribute.get( i );
final AttributeMapping idClassAttributeMapping = getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
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
else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttribute.get( i ) instanceof ToOneAttributeMapping ) ) {
&& !( getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse()
@ -339,6 +338,11 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
return getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return attributeMappings.get( position );
}
@Override
public EntityMappingType findContainingEntityMapping() {
return idMapping.findContainingEntityMapping();
@ -415,12 +419,10 @@ public class IdClassEmbeddable extends AbstractEmbeddableMapping implements Iden
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
final List<AttributeMapping> attributeMappings = getAttributeMappings();
// todo (6.0) : reduce to-one values to id here?
final Object[] result = new Object[ attributeMappings.size() ];
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
final Object[] result = new Object[ getNumberOfAttributeMappings() ];
for ( int i = 0; i < result.length; i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
Object o = attributeMapping.getPropertyAccess().getGetter().get( value );
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.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/**
* The inverse part of a "non-aggregated" composite identifier.
@ -153,31 +154,31 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
navigablePath,
getContainingTableExpression()
);
int offset = 0;
for ( AttributeMapping attributeMapping : identifierValueMapper.getAttributeMappings() ) {
offset += attributeMapping.forEachSelectable(
offset,
(columnIndex, selection) -> {
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
? defaultTableReference
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
selection,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
);
identifierValueMapper.forEachSelectable(
0,
(columnIndex, selection) -> {
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
? defaultTableReference
: tableGroup.resolveTableReference(
navigablePath,
selection.getContainingTableExpression()
);
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
selection,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
);
columnReferences.add( (ColumnReference) columnReference );
}
);
}
columnReferences.add( (ColumnReference) columnReference );
}
);
return new SqlTuple( columnReferences, this );
}
@ -196,14 +197,13 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
null,
null//sessionFactory
);
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings();
final List<AttributeMapping> idClassAttributeMappings = identifierValueMapper.getAttributeMappings();
final Object[] propertyValues = new Object[attributeMappings.size()];
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
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 );
if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttributeMappings.get( i );
final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
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
else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttributeMappings.get( i ) instanceof ToOneAttributeMapping ) ) {
&& !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse()
@ -240,39 +240,35 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
@Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
final List<AttributeMapping> mappedIdAttributeMappings = identifierValueMapper.getAttributeMappings();
final Object[] propertyValues = new Object[mappedIdAttributeMappings.size()];
getEmbeddableTypeDescriptor().forEachAttributeMapping(
(position, attribute) -> {
final AttributeMapping mappedIdAttributeMapping = mappedIdAttributeMappings.get( position );
final Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
.getEntityPersister();
final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final PersistenceContext persistenceContext = session.getPersistenceContext();
// it is conceivable there is a proxy, so check that first
propertyValues[position] = persistenceContext.getProxy( entityKey );
if ( propertyValues[position] == null ) {
// otherwise look for an initialized version
propertyValues[position] = persistenceContext.getEntity( entityKey );
if ( propertyValues[position] == null ) {
propertyValues[position] = entityDescriptor
.findAttributeMapping( toOneAttributeMapping.getAttributeName() )
.getPropertyAccess()
.getGetter()
.get( entity );
}
}
}
else {
propertyValues[position] = o;
final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
for ( int position = 0; position < propertyValues.length; position++ ) {
final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( position );
final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( position );
Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
.getEntityPersister();
final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final PersistenceContext persistenceContext = session.getPersistenceContext();
// it is conceivable there is a proxy, so check that first
o = persistenceContext.getProxy( entityKey );
if ( o == null ) {
// otherwise look for an initialized version
o = persistenceContext.getEntity( entityKey );
if ( o == null ) {
o = entityDescriptor
.findAttributeMapping( toOneAttributeMapping.getAttributeName() )
.getPropertyAccess()
.getGetter()
.get( entity );
}
}
);
getEmbeddableTypeDescriptor().setValues( entity, propertyValues );
}
propertyValues[position] = o;
}
embeddableTypeDescriptor.setValues( entity, propertyValues );
}
@Override
@ -313,6 +309,11 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
@Override
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.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
/**
* A "non-aggregated" composite identifier.
@ -179,31 +180,31 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
navigablePath,
getContainingTableExpression()
);
int offset = 0;
for ( AttributeMapping attributeMapping : identifierValueMapper.getAttributeMappings() ) {
offset += attributeMapping.forEachSelectable(
offset,
(columnIndex, selection) -> {
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
? defaultTableReference
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
selection,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
);
identifierValueMapper.forEachSelectable(
0,
(columnIndex, selection) -> {
final TableReference tableReference = defaultTableReference.resolveTableReference( selection.getContainingTableExpression() ) != null
? defaultTableReference
: tableGroup.resolveTableReference(
navigablePath,
selection.getContainingTableExpression()
);
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
selection.getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
selection,
sqlAstCreationState.getCreationContext().getSessionFactory()
)
);
columnReferences.add( (ColumnReference) columnReference );
}
);
}
columnReferences.add( (ColumnReference) columnReference );
}
);
return new SqlTuple( columnReferences, this );
}
@ -222,14 +223,13 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
null,
sessionFactory
);
final List<AttributeMapping> attributeMappings = getEmbeddableTypeDescriptor().getAttributeMappings();
final List<AttributeMapping> idClassAttributeMappings = identifierValueMapper.getAttributeMappings();
final Object[] propertyValues = new Object[attributeMappings.size()];
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
final Object[] propertyValues = new Object[embeddableTypeDescriptor.getNumberOfAttributeMappings()];
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 );
if ( o == null ) {
final AttributeMapping idClassAttributeMapping = idClassAttributeMappings.get( i );
final AttributeMapping idClassAttributeMapping = identifierValueMapper.getAttributeMapping( i );
if ( idClassAttributeMapping.getPropertyAccess().getGetter().getReturnTypeClass().isPrimitive() ) {
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
else if ( attributeMapping instanceof ToOneAttributeMapping
&& !( idClassAttributeMappings.get( i ) instanceof ToOneAttributeMapping ) ) {
&& !( identifierValueMapper.getAttributeMapping( i ) instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
final ModelPart targetPart = toOneAttributeMapping.getForeignKeyDescriptor().getPart(
toOneAttributeMapping.getSideNature().inverse()
@ -266,39 +266,35 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
@Override
public void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session) {
final List<AttributeMapping> mappedIdAttributeMappings = identifierValueMapper.getAttributeMappings();
final Object[] propertyValues = new Object[mappedIdAttributeMappings.size()];
getEmbeddableTypeDescriptor().forEachAttributeMapping(
(position, attribute) -> {
final AttributeMapping mappedIdAttributeMapping = mappedIdAttributeMappings.get( position );
final Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
.getEntityPersister();
final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final PersistenceContext persistenceContext = session.getPersistenceContext();
// it is conceivable there is a proxy, so check that first
propertyValues[position] = persistenceContext.getProxy( entityKey );
if ( propertyValues[position] == null ) {
// otherwise look for an initialized version
propertyValues[position] = persistenceContext.getEntity( entityKey );
if ( propertyValues[position] == null ) {
// get the association out of the entity itself
propertyValues[position] = entityDescriptor.getPropertyValue(
entity,
toOneAttributeMapping.getAttributeName()
);
}
}
}
else {
propertyValues[position] = o;
final Object[] propertyValues = new Object[identifierValueMapper.getNumberOfAttributeMappings()];
final EmbeddableMappingType embeddableTypeDescriptor = getEmbeddableTypeDescriptor();
for ( int i = 0; i < propertyValues.length; i++ ) {
final AttributeMapping attribute = embeddableTypeDescriptor.getAttributeMapping( i );
final AttributeMapping mappedIdAttributeMapping = identifierValueMapper.getAttributeMapping( i );
Object o = mappedIdAttributeMapping.getPropertyAccess().getGetter().get( id );
if ( attribute instanceof ToOneAttributeMapping && !( mappedIdAttributeMapping instanceof ToOneAttributeMapping ) ) {
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attribute;
final EntityPersister entityPersister = toOneAttributeMapping.getEntityMappingType()
.getEntityPersister();
final EntityKey entityKey = session.generateEntityKey( o, entityPersister );
final PersistenceContext persistenceContext = session.getPersistenceContext();
// it is conceivable there is a proxy, so check that first
o = persistenceContext.getProxy( entityKey );
if ( o == null ) {
// otherwise look for an initialized version
o = persistenceContext.getEntity( entityKey );
if ( o == null ) {
// get the association out of the entity itself
o = entityDescriptor.getPropertyValue(
entity,
toOneAttributeMapping.getAttributeName()
);
}
}
);
getEmbeddableTypeDescriptor().setValues( entity, propertyValues );
}
propertyValues[i] = o;
}
embeddableTypeDescriptor.setValues( entity, propertyValues );
}
@Override
@ -339,6 +335,11 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
@Override
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 );
}
@Override
public int getNumberOfFetchables() {
return indexDescriptor == null ? 1 : 2;
}
@Override
public String toString() {
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.FetchOptions;
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.entity.EntityFetch;
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
@ -1546,6 +1547,11 @@ public class ToOneAttributeMapping
return getEntityMappingType().getNumberOfFetchables();
}
@Override
public Fetchable getFetchable(int position) {
return getEntityMappingType().getFetchable( position );
}
@Override
public TableGroupJoin createTableGroupJoin(
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.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
@ -257,6 +258,11 @@ public class VirtualIdEmbeddable extends AbstractEmbeddableMapping implements Id
return getNumberOfAttributeMappings();
}
@Override
public Fetchable getFetchable(int position) {
return attributeMappings.get( position );
}
@Override
public EntityMappingType 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.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode;
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
@ -1970,55 +1971,56 @@ public abstract class AbstractEntityPersister
}
private List<Fetch> fetchProcessor(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState) {
final List<Fetch> fetches = new ArrayList<>();
final String rootTableName = getRootTableName();
fetchParent.getReferencedMappingContainer().visitFetchables(
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();
}
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
final int size = fetchableContainer.getNumberOfFetchables();
final List<Fetch> fetches = new ArrayList<>( size );
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 );
}
for ( int i = 0; i < size; i++ ) {
final Fetchable fetchable = fetchableContainer.getFetchable( i );
// 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 ) {
continue;
}
},
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;
}
@ -5084,31 +5086,23 @@ public abstract class AbstractEntityPersister
}
else {
if ( hasSubclasses() ) {
visitAttributeMappings(
attribute -> {
final int stateArrayPosition = attribute.getStateArrayPosition();
final Object value = values[stateArrayPosition];
if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set( object, value );
}
}
);
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final Object value = values[i];
if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attributeMappings.get( i ).getPropertyAccess().getSetter();
setter.set( object, value );
}
}
}
else {
visitFetchables(
fetchable -> {
final AttributeMapping attribute = (AttributeMapping) fetchable;
final int stateArrayPosition = attribute.getStateArrayPosition();
final Object value = values[stateArrayPosition];
if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set( object, value );
}
},
null
);
for ( int i = 0; i < staticFetchableList.size(); i++ ) {
final AttributeMapping attribute = (AttributeMapping) staticFetchableList.get( i );
final Object value = values[i];
if ( value != UNFETCHED_PROPERTY ) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set( object, value );
}
}
}
}
}
@ -6101,7 +6095,7 @@ public abstract class AbstractEntityPersister
@Override
public void visitDeclaredAttributeMappings(Consumer<? super AttributeMapping> action) {
declaredAttributeMappings.forEach( (key,value) -> action.accept( value ) );
declaredAttributeMappings.values().forEach( action );
}
@Override
@ -6700,22 +6694,33 @@ public abstract class AbstractEntityPersister
}
@Override
public void visitKeyFetchables(
Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
// final EntityIdentifierMapping identifierMapping = getIdentifierMapping();
// if ( identifierMapping instanceof FetchableContainer ) {
// // essentially means the entity has a composite id - ask the embeddable to visit its fetchables
// ( (FetchableContainer) identifierMapping ).visitFetchables( fetchableConsumer, treatTargetType );
// }
// else {
// fetchableConsumer.accept( (Fetchable) identifierMapping );
// }
public void visitKeyFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
// No-op
}
@Override
public void visitKeyFetchables(IndexedConsumer<Fetchable> fetchableConsumer, EntityMappingType treatTargetType) {
// No-op
}
@Override
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
@ -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() {
return staticFetchableList;
}
@ -6769,7 +6803,9 @@ public abstract class AbstractEntityPersister
public void visitSubTypeAttributeMappings(Consumer<? super AttributeMapping> action) {
visitAttributeMappings( action );
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
default void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
final List<AttributeMapping> attributeMappings = getAttributeMappings();
if ( domainValue instanceof Object[] ) {
final Object[] values = (Object[]) domainValue;
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
attributeMapping.breakDownJdbcValues( values[ i ], valueConsumer, session );
}
}
else {
for ( int i = 0; i < attributeMappings.size(); i++ ) {
final AttributeMapping attributeMapping = attributeMappings.get( i );
for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
final Object attributeValue = attributeMapping.getPropertyAccess().getGetter().get( domainValue );
attributeMapping.breakDownJdbcValues( attributeValue, valueConsumer, session );
}

View File

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

View File

@ -15,6 +15,7 @@ import java.util.function.BiFunction;
import java.util.function.Function;
import org.hibernate.engine.FetchTiming;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
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.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.query.results.ResultsHelper.impl;
@ -70,24 +72,22 @@ public class ImplicitFetchBuilderEntity implements ImplicitFetchBuilder {
final MappingType partMappingType = foreignKeyDescriptor.getPartMappingType();
if ( partMappingType instanceof EmbeddableMappingType ) {
final EmbeddableMappingType embeddableValuedModelPart = (EmbeddableMappingType) partMappingType;
fetchBuilders = new LinkedHashMap<>( embeddableValuedModelPart.getNumberOfFetchables() );
embeddableValuedModelPart.visitFetchables(
subFetchable -> {
final NavigablePath subFetchPath = associationKeyFetchPath.append( subFetchable.getFetchableName() );
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver
.apply( subFetchPath.getFullPath() );
if ( explicitFetchBuilder == null ) {
fetchBuilders.put(
subFetchPath,
Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl )
);
}
else {
fetchBuilders.put( subFetchPath, explicitFetchBuilder );
}
},
null
);
final int size = embeddableValuedModelPart.getNumberOfFetchables();
fetchBuilders = CollectionHelper.linkedMapOfSize( size );
for ( int i = 0; i < size; i++ ) {
final Fetchable subFetchable = embeddableValuedModelPart.getFetchable( i );
final NavigablePath subFetchPath = associationKeyFetchPath.append( subFetchable.getFetchableName() );
final FetchBuilder explicitFetchBuilder = fetchBuilderResolver.apply( subFetchPath.getFullPath() );
if ( explicitFetchBuilder == null ) {
fetchBuilders.put(
subFetchPath,
Builders.implicitFetchBuilder( fetchPath, subFetchable, creationStateImpl )
);
}
else {
fetchBuilders.put( subFetchPath, explicitFetchBuilder );
}
}
}
else {
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.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiation;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
@ -5356,7 +5357,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
else {
for ( int i = 0; i < size; i++ ) {
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMappings().get( i );
final AttributeMapping attributeMapping = embeddableMappingType.getAttributeMapping( i );
inferrableTypeAccessStack.push( () -> attributeMapping );
try {
expressions.add( (Expression) groupedExpressions.get( i ).accept( this ) );
@ -7092,10 +7093,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override
public List<Fetch> visitFetches(FetchParent fetchParent) {
final List<Fetch> fetches = CollectionHelper.arrayList( fetchParent.getReferencedMappingType().getNumberOfFetchables() );
fetchParent.getReferencedMappingContainer().visitKeyFetchables( fetchable -> addFetch( fetches, fetchParent, fetchable, true ), null );
fetchParent.getReferencedMappingContainer().visitFetchables( fetchable -> addFetch( fetches, fetchParent, fetchable, false ), null );
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
final int keySize = referencedMappingContainer.getNumberOfKeyFetchables();
final int size = referencedMappingContainer.getNumberOfFetchables();
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;
}

View File

@ -6,8 +6,12 @@
*/
package org.hibernate.sql.results.graph;
import java.util.ArrayList;
import java.util.List;
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.ModelPartContainer;
@ -17,21 +21,71 @@ import org.hibernate.metamodel.mapping.ModelPartContainer;
* @author Steve Ebersole
*/
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
*/
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(
Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
// 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(
Consumer<Fetchable> fetchableConsumer,
EntityMappingType treatTargetType) {
//noinspection unchecked
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.Fetch;
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.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.entity.EntityInitializer;
@ -90,22 +91,19 @@ public abstract class AbstractEmbeddableInitializer extends AbstractFetchParentA
this.representationStrategy = representationEmbeddable.getRepresentationStrategy();
this.usesStandardInstantiation = representationStrategy.getInstantiator() instanceof StandardEmbeddableInstantiator;
final int numOfAttrs = embeddableTypeDescriptor.getNumberOfAttributeMappings();
this.rowState = new Object[ numOfAttrs ];
this.assemblers = arrayList( numOfAttrs );
final int size = embeddableTypeDescriptor.getNumberOfFetchables();
this.rowState = new Object[ size ];
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(
stateArrayContributor -> {
final Fetch fetch = resultDescriptor.findFetch( stateArrayContributor );
final DomainResultAssembler<?> stateAssembler = fetch == null
? new NullValueAssembler<>( stateArrayContributor.getJavaType() )
: fetch.createAssembler( this, creationState );
final DomainResultAssembler<?> stateAssembler = fetch == null
? new NullValueAssembler<>( stateArrayContributor.getJavaType() )
: fetch.createAssembler( this, creationState );
assemblers.add( stateAssembler );
},
null
);
assemblers.add( stateAssembler );
}
// We never want to create empty composites for the FK target or PK, otherwise collections would break
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.internal.util.NullnessHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
@ -165,32 +166,29 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
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(
fetchable -> {
final AttributeMapping attributeMapping = (AttributeMapping) fetchable;
// todo (6.0) : somehow we need to track whether all state is loaded/resolved
// note that lazy proxies or uninitialized collections count against
// that in the affirmative
// todo (6.0) : somehow we need to track whether all state is loaded/resolved
// note that lazy proxies or uninitialized collections count against
// that in the affirmative
final Fetch fetch = resultDescriptor.findFetch( attributeMapping );
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;
if ( fetch == null ) {
stateAssembler = new NullValueAssembler<>(
attributeMapping.getMappedType().getMappedJavaType()
);
}
else {
stateAssembler = fetch.createAssembler( this, creationState );
}
assemblerMap.put( attributeMapping, stateAssembler );
},
null
);
assemblerMap.put( attributeMapping, stateAssembler );
}
}
private static void deepCopy(

View File

@ -34,7 +34,7 @@ public class EmbeddedComponentType extends ComponentType {
}
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 Getter getter = attributeMapping.getPropertyAccess().getGetter();
final Method getterMethod = getter.getMethod();