Cleanup the circular handling of fetch building of embeddable FKs. Use the target navigable path for target FK domain results
This commit is contained in:
parent
1a24c93155
commit
a7ed354af9
|
@ -693,15 +693,17 @@ public class LoaderSelectBuilder {
|
|||
fetchablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
}
|
||||
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
fetchablePath,
|
||||
fetchParent,
|
||||
creationState
|
||||
);
|
||||
if ( !creationState.isResolvingCircularFetch() ) {
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
fetchablePath,
|
||||
fetchParent,
|
||||
creationState
|
||||
);
|
||||
|
||||
if ( biDirectionalFetch != null ) {
|
||||
fetches.add( biDirectionalFetch );
|
||||
return;
|
||||
if ( biDirectionalFetch != null ) {
|
||||
fetches.add( biDirectionalFetch );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final LockMode lockMode = LockMode.READ;
|
||||
|
|
|
@ -55,6 +55,7 @@ public class LoaderSqlAstCreationState
|
|||
private final LockOptions lockOptions;
|
||||
private final FetchProcessor fetchProcessor;
|
||||
|
||||
private boolean resolvingCircularFetch;
|
||||
private Set<AssociationKey> visitedAssociationKeys = new HashSet<>();
|
||||
|
||||
public LoaderSqlAstCreationState(
|
||||
|
@ -114,6 +115,16 @@ public class LoaderSqlAstCreationState
|
|||
return fetchProcessor.visitFetches( fetchParent, processingState.getInflightQueryPart().getFirstQuerySpec(), this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResolvingCircularFetch() {
|
||||
return resolvingCircularFetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResolvingCircularFetch(boolean resolvingCircularFetch) {
|
||||
this.resolvingCircularFetch = resolvingCircularFetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceIdentifierSelection() {
|
||||
return forceIdentifierSelection;
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.hibernate.sql.results.graph.DomainResultCreationState;
|
|||
*/
|
||||
public interface ForeignKeyDescriptor extends VirtualModelPart {
|
||||
String PART_NAME = "{fk}";
|
||||
String TARGET_PART_NAME = "{fk-target}";
|
||||
|
||||
String getKeyTable();
|
||||
|
||||
|
|
|
@ -15,12 +15,15 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|||
import org.hibernate.mapping.IndexedConsumer;
|
||||
import org.hibernate.metamodel.mapping.AssociationKey;
|
||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||
|
@ -239,10 +242,20 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
final NavigablePath fkNavigablePath = navigablePath.append( getPartName() );
|
||||
final NavigablePath resultNavigablePath;
|
||||
if ( associationKey.getTable().equals( columnContainingTable ) ) {
|
||||
// todo (6.0): what if we append the actual model part and maybe prefix with `{element}`
|
||||
// resultNavigablePath = navigablePath.append( modelPart.getFetchableName() );
|
||||
// todo (6.0): note that the following is only necessary for detecting circular fetch cycles in ToOneAttributeMapping
|
||||
resultNavigablePath = navigablePath.append( ForeignKeyDescriptor.TARGET_PART_NAME );
|
||||
final ModelPartContainer parentModelPart = tableGroup.getModelPart();
|
||||
if ( parentModelPart instanceof PluralAttributeMapping ) {
|
||||
if ( ( (PluralAttributeMapping) parentModelPart ).getIndexDescriptor() == null ) {
|
||||
resultNavigablePath = navigablePath.append( CollectionPart.Nature.ELEMENT.getName() )
|
||||
.append( getPartName() );
|
||||
}
|
||||
else {
|
||||
resultNavigablePath = navigablePath.append( CollectionPart.Nature.INDEX.getName() )
|
||||
.append( getPartName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultNavigablePath = navigablePath.append( getPartName() );
|
||||
}
|
||||
}
|
||||
else {
|
||||
resultNavigablePath = navigablePath.append( getPartName() );
|
||||
|
|
|
@ -532,17 +532,25 @@ public class PluralAttributeMappingImpl
|
|||
NavigablePath fetchablePath,
|
||||
DomainResultCreationState creationState,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
final DomainResult fkResult = getKeyDescriptor().createDomainResult(
|
||||
fetchablePath,
|
||||
sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchParent.getNavigablePath() ),
|
||||
false,
|
||||
creationState
|
||||
);
|
||||
final DomainResult<?> foreignKeyDomainResult;
|
||||
assert !creationState.isResolvingCircularFetch();
|
||||
try {
|
||||
creationState.setResolvingCircularFetch( true );
|
||||
foreignKeyDomainResult = getKeyDescriptor().createDomainResult(
|
||||
fetchablePath,
|
||||
sqlAstCreationState.getFromClauseAccess().getTableGroup( fetchParent.getNavigablePath() ),
|
||||
false,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
finally {
|
||||
creationState.setResolvingCircularFetch( false );
|
||||
}
|
||||
return new DelayedCollectionFetch(
|
||||
fetchablePath,
|
||||
this,
|
||||
fetchParent,
|
||||
fkResult
|
||||
foreignKeyDomainResult
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -380,9 +380,7 @@ public class ToOneAttributeMapping
|
|||
private Key key;
|
||||
}
|
||||
*/
|
||||
if ( parentNavigablePath.getLocalName()
|
||||
.equals( ForeignKeyDescriptor.TARGET_PART_NAME ) || parentNavigablePath.getLocalName().equals(
|
||||
ForeignKeyDescriptor.PART_NAME ) ) {
|
||||
if ( parentNavigablePath.getLocalName().equals( ForeignKeyDescriptor.PART_NAME ) ) {
|
||||
// todo (6.0): maybe it's better to have a flag in creation state that marks if we are building a circular fetch domain result already to skip this?
|
||||
return null;
|
||||
}
|
||||
|
@ -474,6 +472,19 @@ public class ToOneAttributeMapping
|
|||
.getSqlAstCreationState()
|
||||
.getFromClauseAccess()
|
||||
.getTableGroup( fetchParent.getNavigablePath() );
|
||||
final DomainResult<?> foreignKeyDomainResult;
|
||||
assert !creationState.isResolvingCircularFetch();
|
||||
try {
|
||||
creationState.setResolvingCircularFetch( true );
|
||||
foreignKeyDomainResult = foreignKeyDescriptor.createDomainResult(
|
||||
fetchablePath,
|
||||
parentTableGroup,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
finally {
|
||||
creationState.setResolvingCircularFetch( false );
|
||||
}
|
||||
return new CircularFetchImpl(
|
||||
this,
|
||||
getEntityMappingType(),
|
||||
|
@ -482,7 +493,7 @@ public class ToOneAttributeMapping
|
|||
fetchParent,
|
||||
this,
|
||||
fetchablePath,
|
||||
foreignKeyDescriptor.createDomainResult( fetchablePath, parentTableGroup, creationState )
|
||||
foreignKeyDomainResult
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ public class DomainResultCreationStateImpl
|
|||
private final Stack<Function<String, FetchBuilder>> fetchBuilderResolverStack = new StandardStack<>( fetchableName -> null );
|
||||
private final Stack<NavigablePath> relativePathStack = new StandardStack<>();
|
||||
private boolean processingKeyFetches = false;
|
||||
private boolean resolvingCircularFetch;
|
||||
|
||||
public DomainResultCreationStateImpl(
|
||||
String stateIdentifier,
|
||||
|
@ -409,4 +410,14 @@ public class DomainResultCreationStateImpl
|
|||
return fetches;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResolvingCircularFetch() {
|
||||
return resolvingCircularFetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResolvingCircularFetch(boolean resolvingCircularFetch) {
|
||||
this.resolvingCircularFetch = resolvingCircularFetch;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -338,6 +338,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
private final EntityGraphTraversalState entityGraphTraversalState;
|
||||
|
||||
private int fetchDepth;
|
||||
private boolean resolvingCircularFetch;
|
||||
|
||||
private Map<String, FilterPredicate> collectionFilterPredicates;
|
||||
private OrderByFragmentConsumer orderByFragmentConsumer;
|
||||
|
@ -537,9 +538,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
public Stack<Clause> getCurrentClauseStack() {
|
||||
return currentClauseStack;
|
||||
}
|
||||
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// Statements
|
||||
|
||||
@Override
|
||||
|
@ -4459,15 +4458,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final BiConsumer<Fetchable, Boolean> fetchableBiConsumer = (fetchable, isKeyFetchable) -> {
|
||||
final NavigablePath fetchablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
fetchablePath,
|
||||
fetchParent,
|
||||
this
|
||||
);
|
||||
if ( !isResolvingCircularFetch() ) {
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
fetchablePath,
|
||||
fetchParent,
|
||||
this
|
||||
);
|
||||
|
||||
if ( biDirectionalFetch != null ) {
|
||||
fetches.add( biDirectionalFetch );
|
||||
return;
|
||||
if ( biDirectionalFetch != null ) {
|
||||
fetches.add( biDirectionalFetch );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final boolean incrementFetchDepth = fetchable.incrementFetchDepth();
|
||||
|
@ -4688,6 +4689,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResolvingCircularFetch() {
|
||||
return resolvingCircularFetch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResolvingCircularFetch(boolean resolvingCircularFetch) {
|
||||
this.resolvingCircularFetch = resolvingCircularFetch;
|
||||
}
|
||||
|
||||
@Internal
|
||||
public interface SqmAliasedNodeCollector {
|
||||
void next();
|
||||
|
|
|
@ -77,4 +77,8 @@ public interface DomainResultCreationState {
|
|||
* along FetchStyle?
|
||||
*/
|
||||
List<Fetch> visitFetches(FetchParent fetchParent);
|
||||
|
||||
boolean isResolvingCircularFetch();
|
||||
|
||||
void setResolvingCircularFetch(boolean resolvingCircularFetch);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue