diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index ee812e0897..691e213fcb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -157,6 +157,33 @@ public class ToOneAttributeMapping private String identifyingColumnsTableExpression; private boolean canUseParentTableGroup; + protected ToOneAttributeMapping(ToOneAttributeMapping delegate) { + super( + delegate.getAttributeName(), + delegate.getStateArrayPosition(), + delegate.getFetchableKey(), + delegate.getAttributeMetadata(), + delegate.getMappedFetchOptions(), + delegate.getDeclaringType(), + delegate.getPropertyAccess() + ); + navigableRole = delegate.navigableRole; + isInternalLoadNullable = delegate.isInternalLoadNullable; + notFoundAction = delegate.notFoundAction; + unwrapProxy = delegate.unwrapProxy; + isOptional = delegate.isOptional; + entityMappingType = delegate.entityMappingType; + referencedPropertyName = delegate.referencedPropertyName; + targetKeyPropertyName = delegate.targetKeyPropertyName; + cardinality = delegate.cardinality; + bidirectionalAttributePath = delegate.bidirectionalAttributePath; + declaringTableGroupProducer = delegate.declaringTableGroupProducer; + isKeyTableNullable = delegate.isKeyTableNullable; + sqlAliasStem = delegate.sqlAliasStem; + targetKeyPropertyNames = delegate.targetKeyPropertyNames; + isNullable = delegate.isNullable; + foreignKeyDescriptor = delegate.foreignKeyDescriptor; + } public ToOneAttributeMapping( String name, diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java index 91c6f4befc..d8e1965909 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/embeddable/internal/EmbeddableFetchImpl.java @@ -23,6 +23,7 @@ import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Fetchable; +import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableInitializer; import org.hibernate.sql.results.graph.embeddable.EmbeddableResultGraphNode; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; @@ -69,12 +70,20 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab lhsTableGroup.addTableGroupJoin( tableGroupJoin ); return tableGroupJoin.getJoinedGroup(); } - ); afterInitialize( this, creationState ); } + // For Hibernate Reactive + protected EmbeddableFetchImpl(EmbeddableFetchImpl original) { + super( original.getFetchContainer(), original.getNavigablePath() ); + fetchParent = original.fetchParent; + fetchTiming = original.fetchTiming; + tableGroup = original.tableGroup; + hasTableGroup = original.hasTableGroup; + } + @Override public FetchTiming getTiming() { return fetchTiming; @@ -133,11 +142,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab final EmbeddableInitializer initializer = creationState.resolveInitializer( getNavigablePath(), getReferencedModePart(), - () -> new EmbeddableFetchInitializer( - parentAccess, - this, - creationState - ) + () -> buildEmbeddableFetchInitializer( parentAccess, this, creationState ) ).asEmbeddableInitializer(); assert initializer != null; @@ -145,6 +150,13 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab return new EmbeddableAssembler( initializer ); } + protected Initializer buildEmbeddableFetchInitializer( + FetchParentAccess parentAccess, + EmbeddableResultGraphNode embeddableFetch, + AssemblerCreationState creationState) { + return new EmbeddableFetchInitializer( parentAccess, this, creationState ); + } + @Override public boolean appliesTo(GraphImplementor graphImplementor) { return getFetchParent().appliesTo( graphImplementor ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java index a9687b9bdf..62416420c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java @@ -213,10 +213,18 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces return navigablePath; } + protected DomainResultAssembler getIdentifierAssembler() { + return identifierAssembler; + } + protected boolean isMissing() { return missing; } + protected void setMissing(boolean missing) { + this.missing = missing; + } + protected abstract boolean isEntityReturn(); @Override @@ -1138,6 +1146,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces return lockMode; } + protected DomainResultAssembler[][] getAssemblers() { + return assemblers; + } + @Override public void finishUpRow(RowProcessingState rowProcessingState) { final SharedSessionContractImplementor session = rowProcessingState.getSession(); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractNonLazyEntityFetch.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractNonLazyEntityFetch.java index bb47c52309..d8ed2c061a 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractNonLazyEntityFetch.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractNonLazyEntityFetch.java @@ -68,6 +68,10 @@ public abstract class AbstractNonLazyEntityFetch extends AbstractFetchParent imp FetchParentAccess parentAccess, AssemblerCreationState creationState) { final EntityInitializer entityInitializer = getEntityInitializer( parentAccess, creationState ); + return buildEntityAssembler( entityInitializer ); + } + + protected EntityAssembler buildEntityAssembler(EntityInitializer entityInitializer) { return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer ); } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java index e5dff94c06..9a0cabd96f 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchImpl.java @@ -15,7 +15,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.graph.entity.EntityInitializer; /** * @author Andrea Boriero @@ -58,7 +57,7 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch { final Initializer entityInitializer = creationState.resolveInitializer( navigablePath, getEntityValuedModelPart(), - () -> new EntityDelayedFetchInitializer( + () -> buildEntityDelayedFetchInitializer( parentAccess, navigablePath, (ToOneAttributeMapping) getEntityValuedModelPart(), @@ -67,6 +66,20 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch { ) ); + return buildEntityAssembler( entityInitializer ); + } + + protected EntityAssembler buildEntityAssembler(Initializer entityInitializer) { return new EntityAssembler( getFetchedMapping().getJavaType(), entityInitializer.asEntityInitializer() ); } + + protected Initializer buildEntityDelayedFetchInitializer(FetchParentAccess parentAccess, NavigablePath navigablePath, ToOneAttributeMapping entityValuedModelPart, boolean selectByUniqueKey, DomainResultAssembler resultAssembler) { + return new EntityDelayedFetchInitializer( + parentAccess, + navigablePath, + entityValuedModelPart, + selectByUniqueKey, + resultAssembler + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java index 92ebabcdab..96a50015f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedFetchInitializer.java @@ -183,14 +183,14 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp } } - private EntityInitializer getParentEntityInitializer(FetchParentAccess parentAccess) { + protected EntityInitializer getParentEntityInitializer(FetchParentAccess parentAccess) { if ( parentAccess != null ) { return parentAccess.findFirstEntityInitializer(); } return null; } - private static boolean isEnhancedForLazyLoading(EntityInitializer parentEntityIntialiazer) { + protected static boolean isEnhancedForLazyLoading(EntityInitializer parentEntityIntialiazer) { return parentEntityIntialiazer != null && parentEntityIntialiazer.getEntityDescriptor() .getBytecodeEnhancementMetadata() .isEnhancedForLazyLoading(); @@ -219,6 +219,10 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp return entityInstance; } + protected void setEntityInstance(Object entityInstance) { + this.entityInstance = entityInstance; + } + @Override public EntityKey getEntityKey() { throw new UnsupportedOperationException(); @@ -259,4 +263,19 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp return "EntityDelayedFetchInitializer(" + LoggingHelper.toLoggableString( navigablePath ) + ")"; } + protected Object getIdentifier() { + return identifier; + } + + protected void setIdentifier(Object identifier) { + this.identifier = identifier; + } + + protected boolean isSelectByUniqueKey() { + return selectByUniqueKey; + } + + protected DomainResultAssembler getIdentifierAssembler() { + return identifierAssembler; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java index 4d5b3e3395..a8d7eb3266 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityDelayedResultImpl.java @@ -17,7 +17,6 @@ import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.FetchParentAccess; import org.hibernate.sql.results.graph.Initializer; -import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.type.descriptor.java.JavaType; /** @@ -68,18 +67,33 @@ public class EntityDelayedResultImpl implements DomainResult { final Initializer initializer = creationState.resolveInitializer( getNavigablePath(), entityValuedModelPart, - () -> new EntityDelayedFetchInitializer( - null, + () -> buildEntityDelayedFetchInitializer( getNavigablePath(), (ToOneAttributeMapping) entityValuedModelPart, - false, identifierResult.createResultAssembler( parentAccess, creationState ) ) ); + return buildEntityAssembler( initializer ); + } + + protected EntityAssembler buildEntityAssembler(Initializer initializer) { return new EntityAssembler( getResultJavaType(), initializer.asEntityInitializer() ); } + protected Initializer buildEntityDelayedFetchInitializer( + NavigablePath navigablePath, + ToOneAttributeMapping entityValuedModelPart, + DomainResultAssembler resultAssembler) { + return new EntityDelayedFetchInitializer( + null, + navigablePath, + (ToOneAttributeMapping) entityValuedModelPart, + false, + resultAssembler + ); + } + @Override public String toString() { return "EntityDelayedResultImpl {" + getNavigablePath() + "}"; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java index 4fd3fb13af..b18baff180 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityFetchSelectImpl.java @@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph.entity.internal; import org.hibernate.engine.FetchTiming; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.DomainResult; @@ -37,6 +38,14 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch { this.keyResult = keyResult; this.selectByUniqueKey = selectByUniqueKey; + + } + + // For Hibernate Reactive + protected EntityFetchSelectImpl(EntityFetchSelectImpl original) { + super( original.getNavigablePath(), original.getFetchedMapping(), original.getFetchParent() ); + this.keyResult = original.keyResult; + this.selectByUniqueKey = original.selectByUniqueKey; } @Override @@ -56,18 +65,40 @@ public class EntityFetchSelectImpl extends AbstractNonJoinedEntityFetch { final Initializer initializer = creationState.resolveInitializer( getNavigablePath(), getFetchedMapping(), - () -> - EntitySelectFetchInitializerBuilder.createInitializer( - parentAccess, - (ToOneAttributeMapping) getFetchedMapping(), - getReferencedMappingContainer().getEntityPersister(), - keyResult, - getNavigablePath(), - selectByUniqueKey, - creationState - ) + () -> buildEntitySelectFetchInitializer( + parentAccess, + (ToOneAttributeMapping) getFetchedMapping(), + getReferencedMappingContainer().getEntityPersister(), + keyResult, + getNavigablePath(), + selectByUniqueKey, + creationState + ) ); + return buildEntityAssembler( initializer ); + } + + protected Initializer buildEntitySelectFetchInitializer( + FetchParentAccess parentAccess, + ToOneAttributeMapping fetchedMapping, + EntityPersister entityPersister, + DomainResult keyResult, + NavigablePath navigablePath, + boolean selectByUniqueKey, + AssemblerCreationState creationState) { + return EntitySelectFetchInitializerBuilder.createInitializer( + parentAccess, + fetchedMapping, + entityPersister, + keyResult, + navigablePath, + selectByUniqueKey, + creationState + ); + } + + protected DomainResultAssembler buildEntityAssembler(Initializer initializer) { return new EntityAssembler( getResultJavaType(), initializer.asEntityInitializer() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java index 52375829be..144d2ac8ac 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/domain/CircularFetchImpl.java @@ -9,6 +9,7 @@ package org.hibernate.sql.results.internal.domain; import org.hibernate.engine.FetchTiming; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping; +import org.hibernate.persister.entity.EntityPersister; import org.hibernate.spi.NavigablePath; import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.BiDirectionalFetch; @@ -59,7 +60,18 @@ public class CircularFetchImpl implements BiDirectionalFetch { this.referencedNavigablePath = referencedNavigablePath; this.fetchable = fetchable; this.keyResult = keyResult; + } + protected CircularFetchImpl(CircularFetchImpl original) { + this.referencedModelPart = original.referencedModelPart; + this.entityMappingType = original.entityMappingType; + this.timing = original.timing; + this.fetchParent = original.fetchParent; + this.navigablePath = original.navigablePath; + this.selectByUniqueKey = original.selectByUniqueKey; + this.referencedNavigablePath = original.referencedNavigablePath; + this.fetchable = original.fetchable; + this.keyResult = original.keyResult; } @Override @@ -95,28 +107,7 @@ public class CircularFetchImpl implements BiDirectionalFetch { final Initializer initializer = creationState.resolveInitializer( getNavigablePath(), referencedModelPart, - () -> { - if ( timing == FetchTiming.IMMEDIATE ) { - return EntitySelectFetchInitializerBuilder.createInitializer( - parentAccess, - fetchable, - entityMappingType.getEntityPersister(), - keyResult, - getNavigablePath(), - selectByUniqueKey, - creationState - ); - } - else { - return new EntityDelayedFetchInitializer( - parentAccess, - getReferencedPath(), - fetchable, - selectByUniqueKey, - keyResult.createResultAssembler( parentAccess, creationState ) - ); - } - } + () -> initializerFactory( parentAccess, creationState ) ); return new BiDirectionalFetchAssembler( @@ -125,39 +116,96 @@ public class CircularFetchImpl implements BiDirectionalFetch { ); } - - - @Override - public FetchTiming getTiming() { - return timing; + protected Initializer initializerFactory(FetchParentAccess parentAccess, AssemblerCreationState creationState) { + if ( timing == FetchTiming.IMMEDIATE ) { + return buildEntitySelectFetchInitializer( + parentAccess, + fetchable, + entityMappingType.getEntityPersister(), + keyResult, + getNavigablePath(), + selectByUniqueKey, + creationState + ); + } + else { + return buildEntityDelayedFetchInitializer( + parentAccess, + getReferencedPath(), + fetchable, + selectByUniqueKey, + keyResult.createResultAssembler( parentAccess, creationState ) + ); + } } - @Override - public boolean hasTableGroup() { - return true; + protected Initializer buildEntitySelectFetchInitializer( + FetchParentAccess parentAccess, + ToOneAttributeMapping fetchable, + EntityPersister entityPersister, + DomainResult keyResult, + NavigablePath navigablePath, + boolean selectByUniqueKey, + AssemblerCreationState creationState) { + return EntitySelectFetchInitializerBuilder + .createInitializer( + parentAccess, + this.fetchable, + entityPersister, + keyResult, + navigablePath, + selectByUniqueKey, + creationState + ); } - private static class BiDirectionalFetchAssembler implements DomainResultAssembler { - private EntityInitializer initializer; - private JavaType assembledJavaType; + protected Initializer buildEntityDelayedFetchInitializer( + FetchParentAccess parentAccess, + NavigablePath referencedPath, + ToOneAttributeMapping fetchable, + boolean selectByUniqueKey, + DomainResultAssembler resultAssembler) { + return new EntityDelayedFetchInitializer( + parentAccess, + referencedPath, + fetchable, + selectByUniqueKey, + resultAssembler + ); + } - public BiDirectionalFetchAssembler( - EntityInitializer initializer, - JavaType assembledJavaType) { - this.initializer = initializer; - this.assembledJavaType = assembledJavaType; + + @Override + public FetchTiming getTiming ( ) { + return timing; } @Override - public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { - initializer.resolveInstance( rowProcessingState ); - return initializer.getInitializedInstance(); + public boolean hasTableGroup ( ) { + return true; } - @Override - public JavaType getAssembledJavaType() { - return assembledJavaType; + private static class BiDirectionalFetchAssembler implements DomainResultAssembler { + private EntityInitializer initializer; + private JavaType assembledJavaType; + + public BiDirectionalFetchAssembler( + EntityInitializer initializer, + JavaType assembledJavaType) { + this.initializer = initializer; + this.assembledJavaType = assembledJavaType; + } + + @Override + public Object assemble(RowProcessingState rowProcessingState, JdbcValuesSourceProcessingOptions options) { + initializer.resolveInstance( rowProcessingState ); + return initializer.getInitializedInstance(); + } + + @Override + public JavaType getAssembledJavaType() { + return assembledJavaType; + } } + } - -}