HHH-14390 : StackOverflowError with @Fetch(FetchMode.SELECT) mapped for entity with an ID that is a bidirectional one-to-one eager association
Move fix into FetchStyleLoadPlanBuildingAssociationVisitationStrategy
This commit is contained in:
parent
2bacaabc37
commit
cb18fdb4f7
|
@ -237,18 +237,6 @@ public class OneToOneSecondPass implements SecondPass {
|
||||||
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
|
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
|
||||||
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
|
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
|
||||||
|
|
||||||
// If the other side is an entity with an ID that is derived from
|
|
||||||
// this side's owner entity, and both sides of the association are eager,
|
|
||||||
// then this side must be set to FetchMode.SELECT; otherwise,
|
|
||||||
// there will be an infinite loop attempting to load the derived ID on
|
|
||||||
// the opposite side.
|
|
||||||
if ( referencesDerivedId &&
|
|
||||||
!value.isLazy() &&
|
|
||||||
value.getFetchMode() == FetchMode.JOIN &&
|
|
||||||
!otherSideProperty.isLazy() ) {
|
|
||||||
value.setFetchMode( FetchMode.SELECT );
|
|
||||||
}
|
|
||||||
|
|
||||||
String propertyRef = value.getReferencedPropertyName();
|
String propertyRef = value.getReferencedPropertyName();
|
||||||
if ( propertyRef != null ) {
|
if ( propertyRef != null ) {
|
||||||
buildingContext.getMetadataCollector().addUniquePropertyReference(
|
buildingContext.getMetadataCollector().addUniquePropertyReference(
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.CoreLogging;
|
import org.hibernate.internal.CoreLogging;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||||
|
import org.hibernate.loader.plan.spi.EntityReference;
|
||||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||||
import org.hibernate.loader.plan.spi.FetchSource;
|
import org.hibernate.loader.plan.spi.FetchSource;
|
||||||
import org.hibernate.loader.plan.spi.LoadPlan;
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
@ -29,6 +30,8 @@ import org.hibernate.persister.walking.spi.WalkingException;
|
||||||
import org.hibernate.type.CompositeType;
|
import org.hibernate.type.CompositeType;
|
||||||
import org.hibernate.type.EmbeddedComponentType;
|
import org.hibernate.type.EmbeddedComponentType;
|
||||||
import org.hibernate.type.EntityType;
|
import org.hibernate.type.EntityType;
|
||||||
|
import org.hibernate.type.ForeignKeyDirection;
|
||||||
|
import org.hibernate.type.OneToOneType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -252,6 +255,52 @@ public class FetchStyleLoadPlanBuildingAssociationVisitationStrategy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( attributeType.isEntityType() &&
|
||||||
|
fetchStrategy.getTiming() == FetchTiming.IMMEDIATE &&
|
||||||
|
fetchStrategy.getStyle() == FetchStyle.JOIN ) {
|
||||||
|
final EntityType entityType = (EntityType) attributeType;
|
||||||
|
final EntityReference currentEntityReference = currentSource.resolveEntityReference();
|
||||||
|
if ( currentEntityReference != null ) {
|
||||||
|
final EntityPersister currentEntityPersister = currentEntityReference.getEntityPersister();
|
||||||
|
if ( entityType.isOneToOne() && entityType.getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
|
||||||
|
// attributeDefinition is the "mappedBy" (inverse) side of a
|
||||||
|
// bidirectional one-to-one association.
|
||||||
|
final OneToOneType oneToOneType = (OneToOneType) attributeType;
|
||||||
|
final String associatedUniqueKeyPropertyName = oneToOneType.getIdentifierOrUniqueKeyPropertyName(
|
||||||
|
sessionFactory()
|
||||||
|
);
|
||||||
|
if ( associatedUniqueKeyPropertyName == null ) {
|
||||||
|
// The foreign key for the other side of the association is the ID.
|
||||||
|
// Now check if the ID itself is the other side of the association.
|
||||||
|
final EntityPersister associatedEntityPersister = (EntityPersister) oneToOneType.getAssociatedJoinable(
|
||||||
|
sessionFactory()
|
||||||
|
);
|
||||||
|
final Type associatedIdentifierType = associatedEntityPersister.getIdentifierType();
|
||||||
|
if ( associatedIdentifierType.isComponentType() &&
|
||||||
|
( (CompositeType) associatedIdentifierType ).isEmbedded() ) {
|
||||||
|
final EmbeddedComponentType associatedNonEncapsulatedIdentifierType =
|
||||||
|
(EmbeddedComponentType) associatedIdentifierType;
|
||||||
|
if ( associatedNonEncapsulatedIdentifierType.getSubtypes().length == 1 &&
|
||||||
|
EntityType.class.isInstance( associatedNonEncapsulatedIdentifierType.getSubtypes()[0] ) ) {
|
||||||
|
final EntityType otherSideEntityType =
|
||||||
|
( (EntityType) associatedNonEncapsulatedIdentifierType.getSubtypes()[0] );
|
||||||
|
if ( otherSideEntityType.isLogicalOneToOne() &&
|
||||||
|
otherSideEntityType.isReferenceToPrimaryKey() &&
|
||||||
|
otherSideEntityType.getAssociatedEntityName().equals( currentEntityPersister.getEntityName() ) ) {
|
||||||
|
// The associated entity's ID is the other side of the association.
|
||||||
|
// This side must be set to FetchMode.SELECT; otherwise,
|
||||||
|
// there will be an infinite loop because the current entity
|
||||||
|
// would need to be loaded before the associated entity can be loaded,
|
||||||
|
// but the associated entity cannot be loaded until after the current
|
||||||
|
// entity is loaded (since the current entity is the associated entity's ID).
|
||||||
|
return new FetchStrategy( fetchStrategy.getTiming(), FetchStyle.SELECT );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return fetchStrategy;
|
return fetchStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue