HHH-8722 HHH-8723 : Reorg AbstractLoadPlanBuildingAssociationVisitationStrategy and add Any support
This commit is contained in:
parent
4e6f3a9753
commit
de7cddc879
|
@ -390,6 +390,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
final Type attributeType = attributeDefinition.getType();
|
||||
|
||||
final boolean isAnyType = attributeType.isAnyType();
|
||||
final boolean isComponentType = attributeType.isComponentType();
|
||||
final boolean isAssociationType = attributeType.isAssociationType();
|
||||
final boolean isBasicType = ! ( isComponentType || isAssociationType );
|
||||
|
@ -397,6 +398,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
if ( isBasicType ) {
|
||||
return true;
|
||||
}
|
||||
else if ( isAnyType ) {
|
||||
// If isAnyType is true, then isComponentType and isAssociationType will also be true
|
||||
// so need to check isAnyType first so that it is handled properly.
|
||||
return handleAnyAttribute( (AssociationAttributeDefinition) attributeDefinition );
|
||||
}
|
||||
else if ( isAssociationType ) {
|
||||
return handleAssociationAttribute( (AssociationAttributeDefinition) attributeDefinition );
|
||||
}
|
||||
|
@ -553,7 +559,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
}
|
||||
|
||||
@Override
|
||||
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
|
||||
public void foundAny(AnyMappingDefinition anyDefinition) {
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
protected boolean handleAnyAttribute(AssociationAttributeDefinition attributeDefinition) {
|
||||
// for ANY mappings we need to build a Fetch:
|
||||
// 1) fetch type is SELECT, timing might be IMMEDIATE or DELAYED depending on whether it was defined as lazy
|
||||
// 2) (because the fetch cannot be a JOIN...) do not push it to the stack
|
||||
|
@ -564,10 +574,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
fetchOwner.buildAnyFetch(
|
||||
attributeDefinition,
|
||||
anyDefinition,
|
||||
attributeDefinition.toAnyDefinition(),
|
||||
fetchStrategy,
|
||||
this
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {
|
||||
|
|
|
@ -25,7 +25,9 @@ package org.hibernate.loader.plan2.build.spi;
|
|||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.logging.MDC;
|
||||
|
@ -91,6 +93,8 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
|
||||
private final ArrayDeque<ExpandingFetchSource> fetchSourceStack = new ArrayDeque<ExpandingFetchSource>();
|
||||
|
||||
private final Set<AttributeDefinition> pushedAttributes = new HashSet<AttributeDefinition>( );
|
||||
|
||||
protected AbstractLoadPlanBuildingAssociationVisitationStrategy(SessionFactoryImplementor sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.querySpaces = new QuerySpacesImpl( sessionFactory );
|
||||
|
@ -151,6 +155,7 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
propertyPathStack.pop();
|
||||
MDC.remove( MDC_KEY );
|
||||
fetchSourceStack.clear();
|
||||
pushedAttributes.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,6 +203,15 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
|
||||
@Override
|
||||
public void finishingEntity(EntityDefinition entityDefinition) {
|
||||
final boolean isRoot = fetchSourceStack.size() == 1 && collectionReferenceStack.isEmpty();
|
||||
if ( !isRoot ) {
|
||||
return;
|
||||
}
|
||||
|
||||
popEntityFromStack( entityDefinition );
|
||||
}
|
||||
|
||||
private void popEntityFromStack(EntityDefinition entityDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this entity
|
||||
final ExpandingFetchSource fetchSource = popFromStack();
|
||||
|
||||
|
@ -370,10 +384,19 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
|
||||
@Override
|
||||
public void finishingCollection(CollectionDefinition collectionDefinition) {
|
||||
final boolean isRoot = fetchSourceStack.isEmpty() && collectionReferenceStack.size() == 1;
|
||||
if ( !isRoot ) {
|
||||
return;
|
||||
}
|
||||
|
||||
popFromCollectionStack( collectionDefinition );
|
||||
}
|
||||
|
||||
private void popFromCollectionStack(CollectionDefinition collectionDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this collection
|
||||
final CollectionReference collectionReference = popFromCollectionStack();
|
||||
if ( ! collectionReference.getCollectionPersister().equals( collectionDefinition.getCollectionPersister() ) ) {
|
||||
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
|
||||
throw new WalkingException( "Mismatched CollectionReference from stack on pop" );
|
||||
}
|
||||
|
||||
log.tracef(
|
||||
|
@ -426,14 +449,17 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
return;
|
||||
}
|
||||
|
||||
if ( indexType.isComponentType() ) {
|
||||
if ( indexType.isEntityType() || indexType.isComponentType() ) {
|
||||
// todo : validate the stack?
|
||||
popFromStack();
|
||||
|
||||
final ExpandingFetchSource fetchSource = popFromStack();
|
||||
if ( !CollectionFetchableIndex.class.isInstance( fetchSource ) ) {
|
||||
throw new WalkingException(
|
||||
"CollectionReference did not return an expected index graph : " +
|
||||
indexDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// entity indexes would be popped during finishingEntity processing
|
||||
|
||||
log.tracef(
|
||||
"%s Finished collection index graph : %s",
|
||||
StringHelper.repeat( "<<", fetchSourceStack.size() ),
|
||||
|
@ -484,19 +510,16 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
return;
|
||||
}
|
||||
|
||||
if ( elementType.isComponentType() ) {
|
||||
if ( elementType.isComponentType() || elementType.isAssociationType()) {
|
||||
// pop it from the stack
|
||||
final ExpandingFetchSource popped = popFromStack();
|
||||
|
||||
// validation
|
||||
|
||||
if ( ! CollectionFetchableElement.class.isInstance( popped ) ) {
|
||||
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
|
||||
}
|
||||
}
|
||||
|
||||
// entity indexes would be popped during finishingEntity processing
|
||||
|
||||
log.tracef(
|
||||
"%s Finished collection element graph : %s",
|
||||
StringHelper.repeat( "<<", fetchSourceStack.size() ),
|
||||
|
@ -512,22 +535,22 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
compositionDefinition.getName()
|
||||
);
|
||||
|
||||
if ( fetchSourceStack.isEmpty() ) {
|
||||
if ( fetchSourceStack.isEmpty() && collectionReferenceStack.isEmpty() ) {
|
||||
throw new HibernateException( "A component cannot be the root of a walk nor a graph" );
|
||||
}
|
||||
|
||||
final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( compositionDefinition );
|
||||
pushToStack( (ExpandingFetchSource) compositeFetch );
|
||||
//final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( compositionDefinition );
|
||||
//pushToStack( (ExpandingFetchSource) compositeFetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingComposite(CompositionDefinition compositionDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this composition
|
||||
final ExpandingFetchSource popped = popFromStack();
|
||||
//final ExpandingFetchSource popped = popFromStack();
|
||||
|
||||
if ( ! CompositeFetch.class.isInstance( popped ) ) {
|
||||
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
|
||||
}
|
||||
//if ( ! CompositeFetch.class.isInstance( popped ) ) {
|
||||
// throw new WalkingException( "Mismatched FetchSource from stack on pop" );
|
||||
//}
|
||||
|
||||
log.tracef(
|
||||
"%s Finishing composite : %s",
|
||||
|
@ -546,6 +569,7 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
|
||||
final Type attributeType = attributeDefinition.getType();
|
||||
|
||||
final boolean isAnyType = attributeType.isAnyType();
|
||||
final boolean isComponentType = attributeType.isComponentType();
|
||||
final boolean isAssociationType = attributeType.isAssociationType();
|
||||
final boolean isBasicType = ! ( isComponentType || isAssociationType );
|
||||
|
@ -553,6 +577,11 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
if ( isBasicType ) {
|
||||
return true;
|
||||
}
|
||||
else if ( isAnyType ) {
|
||||
// If isAnyType is true, then isComponentType and isAssociationType will also be true
|
||||
// so need to check isAnyType first so that it is handled properly.
|
||||
return handleAnyAttribute( (AssociationAttributeDefinition) attributeDefinition );
|
||||
}
|
||||
else if ( isAssociationType ) {
|
||||
return handleAssociationAttribute( (AssociationAttributeDefinition) attributeDefinition );
|
||||
}
|
||||
|
@ -563,6 +592,46 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
|
||||
@Override
|
||||
public void finishingAttribute(AttributeDefinition attributeDefinition) {
|
||||
if ( pushedAttributes.contains( attributeDefinition ) ) {
|
||||
final Type attributeType = attributeDefinition.getType();
|
||||
if ( attributeType.isComponentType() ) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this composition
|
||||
final ExpandingFetchSource popped = popFromStack();
|
||||
if ( ! CompositeFetch.class.isInstance( popped ) ) {
|
||||
throw new WalkingException( "Mismatched FetchSource from stack on pop" );
|
||||
}
|
||||
}
|
||||
else if ( attributeType.isAssociationType() ) {
|
||||
final AssociationAttributeDefinition associationAttributeDefinition =
|
||||
(AssociationAttributeDefinition) attributeDefinition;
|
||||
if ( attributeType.isCollectionType() ) {
|
||||
popFromCollectionStack( associationAttributeDefinition.toCollectionDefinition() );
|
||||
}
|
||||
else if ( attributeType.isEntityType() ) {
|
||||
popEntityFromStack( associationAttributeDefinition.toEntityDefinition() );
|
||||
}
|
||||
else {
|
||||
throw new WalkingException(
|
||||
String.format(
|
||||
"Unexpected attribute of type [%s] was pushed: %s",
|
||||
associationAttributeDefinition.getType(),
|
||||
associationAttributeDefinition
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new WalkingException(
|
||||
String.format(
|
||||
"Unexpected attribute of type [%s] was pushed: %s",
|
||||
attributeDefinition.getType(),
|
||||
attributeDefinition
|
||||
)
|
||||
);
|
||||
}
|
||||
pushedAttributes.remove( attributeDefinition );
|
||||
}
|
||||
|
||||
log.tracef(
|
||||
"%s Finishing up attribute : %s",
|
||||
StringHelper.repeat( "<<", fetchSourceStack.size() ),
|
||||
|
@ -759,7 +828,11 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
// }
|
||||
|
||||
@Override
|
||||
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
|
||||
public void foundAny(AnyMappingDefinition anyDefinition) {
|
||||
// do nothing.
|
||||
}
|
||||
|
||||
protected boolean handleAnyAttribute(AssociationAttributeDefinition attributeDefinition) {
|
||||
// for ANY mappings we need to build a Fetch:
|
||||
// 1) fetch type is SELECT, timing might be IMMEDIATE or DELAYED depending on whether it was defined as lazy
|
||||
// 2) (because the fetch cannot be a JOIN...) do not push it to the stack
|
||||
|
@ -774,12 +847,13 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
// fetchStrategy,
|
||||
// this
|
||||
// );
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleCompositeAttribute(CompositionDefinition attributeDefinition) {
|
||||
// final ExpandingFetchSource currentSource = currentSource();
|
||||
// final CompositeFetch fetch = currentSource.buildCompositeFetch( attributeDefinition, this );
|
||||
// pushToStack( (ExpandingFetchSource) fetch );
|
||||
final CompositeFetch compositeFetch = currentSource().buildCompositeFetch( attributeDefinition );
|
||||
pushToStack( (ExpandingFetchSource) compositeFetch );
|
||||
pushedAttributes.add( attributeDefinition );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -814,6 +888,9 @@ public abstract class AbstractLoadPlanBuildingAssociationVisitationStrategy
|
|||
pushToCollectionStack( fetch );
|
||||
}
|
||||
}
|
||||
if ( fetchStrategy.getStyle() == FetchStyle.JOIN ) {
|
||||
pushedAttributes.add( attributeDefinition );
|
||||
}
|
||||
return fetchStrategy.getStyle() == FetchStyle.JOIN;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ public interface AssociationVisitationStrategy {
|
|||
*/
|
||||
public void finishingAttribute(AttributeDefinition attributeDefinition);
|
||||
|
||||
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition);
|
||||
public void foundAny(AnyMappingDefinition anyDefinition);
|
||||
|
||||
public void associationKeyRegistered(AssociationKey associationKey);
|
||||
public FetchSource registeredFetchSource(AssociationKey associationKey);
|
||||
|
|
|
@ -128,12 +128,12 @@ public class MetamodelGraphWalker {
|
|||
final EncapsulatedEntityIdentifierDefinition idAsEncapsulated = (EncapsulatedEntityIdentifierDefinition) identifierDefinition;
|
||||
final AttributeDefinition idAttr = idAsEncapsulated.getAttributeDefinition();
|
||||
if ( CompositionDefinition.class.isInstance( idAttr ) ) {
|
||||
visitAttributes( (CompositionDefinition) idAttr );
|
||||
visitCompositeDefinition( (CompositionDefinition) idAttr );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// NonEncapsulatedEntityIdentifierDefinition itself is defined as a CompositionDefinition
|
||||
visitAttributes( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
|
||||
visitCompositeDefinition( (NonEncapsulatedEntityIdentifierDefinition) identifierDefinition );
|
||||
}
|
||||
|
||||
strategy.finishingEntityIdentifier( identifierDefinition );
|
||||
|
@ -196,7 +196,7 @@ public class MetamodelGraphWalker {
|
|||
|
||||
final AssociationAttributeDefinition.AssociationNature nature = attribute.getAssociationNature();
|
||||
if ( nature == AssociationAttributeDefinition.AssociationNature.ANY ) {
|
||||
visitAnyDefinition( attribute, attribute.toAnyDefinition() );
|
||||
visitAnyDefinition( attribute.toAnyDefinition() );
|
||||
}
|
||||
else if ( nature == AssociationAttributeDefinition.AssociationNature.COLLECTION ) {
|
||||
visitCollectionDefinition( attribute.toCollectionDefinition() );
|
||||
|
@ -206,8 +206,8 @@ public class MetamodelGraphWalker {
|
|||
}
|
||||
}
|
||||
|
||||
private void visitAnyDefinition(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
|
||||
strategy.foundAny( attributeDefinition, anyDefinition );
|
||||
private void visitAnyDefinition(AnyMappingDefinition anyDefinition) {
|
||||
strategy.foundAny( anyDefinition );
|
||||
}
|
||||
|
||||
private void visitCompositeDefinition(CompositionDefinition compositionDefinition) {
|
||||
|
@ -241,7 +241,7 @@ public class MetamodelGraphWalker {
|
|||
try {
|
||||
final Type collectionIndexType = collectionIndexDefinition.getType();
|
||||
if ( collectionIndexType.isComponentType() ) {
|
||||
visitAttributes( collectionIndexDefinition.toCompositeDefinition() );
|
||||
visitCompositeDefinition( collectionIndexDefinition.toCompositeDefinition() );
|
||||
}
|
||||
else if ( collectionIndexType.isAssociationType() ) {
|
||||
visitEntityDefinition( collectionIndexDefinition.toEntityDefinition() );
|
||||
|
@ -259,7 +259,7 @@ public class MetamodelGraphWalker {
|
|||
strategy.startingCollectionElements( elementDefinition );
|
||||
|
||||
if ( elementDefinition.getType().isComponentType() ) {
|
||||
visitAttributes( elementDefinition.toCompositeElementDefinition() );
|
||||
visitCompositeDefinition( elementDefinition.toCompositeElementDefinition() );
|
||||
}
|
||||
else if ( elementDefinition.getType().isEntityType() ) {
|
||||
if ( ! collectionDefinition.getCollectionPersister().isOneToMany() ) {
|
||||
|
|
|
@ -230,7 +230,7 @@ public class LoggingAssociationVisitationStrategy implements AssociationVisitati
|
|||
// }
|
||||
|
||||
@Override
|
||||
public void foundAny(AssociationAttributeDefinition attributeDefinition, AnyMappingDefinition anyDefinition) {
|
||||
public void foundAny(AnyMappingDefinition anyDefinition) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue