HHH-17572 Move embedded collections selection check to query validation
This commit is contained in:
parent
f88ef3e7c2
commit
b9e230e456
|
@ -15,7 +15,6 @@ import java.util.Set;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.metamodel.mapping.CollectionPart;
|
import org.hibernate.metamodel.mapping.CollectionPart;
|
||||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||||
import org.hibernate.query.sqm.FetchClauseType;
|
|
||||||
import org.hibernate.query.SemanticException;
|
import org.hibernate.query.SemanticException;
|
||||||
import org.hibernate.query.criteria.JpaExpression;
|
import org.hibernate.query.criteria.JpaExpression;
|
||||||
import org.hibernate.query.criteria.JpaOrder;
|
import org.hibernate.query.criteria.JpaOrder;
|
||||||
|
@ -23,10 +22,12 @@ import org.hibernate.query.criteria.JpaPredicate;
|
||||||
import org.hibernate.query.criteria.JpaQueryStructure;
|
import org.hibernate.query.criteria.JpaQueryStructure;
|
||||||
import org.hibernate.query.criteria.JpaRoot;
|
import org.hibernate.query.criteria.JpaRoot;
|
||||||
import org.hibernate.query.criteria.JpaSelection;
|
import org.hibernate.query.criteria.JpaSelection;
|
||||||
|
import org.hibernate.query.sqm.FetchClauseType;
|
||||||
import org.hibernate.query.sqm.NodeBuilder;
|
import org.hibernate.query.sqm.NodeBuilder;
|
||||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||||
import org.hibernate.query.sqm.tree.SqmNode;
|
import org.hibernate.query.sqm.tree.SqmNode;
|
||||||
|
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
|
||||||
|
@ -47,6 +48,7 @@ import org.hibernate.spi.NavigablePath;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.Expression;
|
import jakarta.persistence.criteria.Expression;
|
||||||
import jakarta.persistence.criteria.Predicate;
|
import jakarta.persistence.criteria.Predicate;
|
||||||
|
import jakarta.persistence.metamodel.SingularAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the commonality between a root query and a subquery.
|
* Defines the commonality between a root query and a subquery.
|
||||||
|
@ -519,6 +521,10 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
collectSelectedFromSet( selectedFromSet, (SqmFrom<?, ?>) path.getLhs() );
|
collectSelectedFromSet( selectedFromSet, (SqmFrom<?, ?>) path.getLhs() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( selectableNode instanceof SqmEmbeddedValuedSimplePath<?> ) {
|
||||||
|
final SqmEmbeddedValuedSimplePath<?> path = (SqmEmbeddedValuedSimplePath<?>) selectableNode;
|
||||||
|
assertEmbeddableCollections( path.getNavigablePath(), (EmbeddableDomainType<?>) path.getSqmType() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void collectSelectedFromSet(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> sqmFrom) {
|
private void collectSelectedFromSet(Set<SqmFrom<?, ?>> selectedFromSet, SqmFrom<?, ?> sqmFrom) {
|
||||||
|
@ -569,6 +575,22 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertEmbeddableCollections(NavigablePath navigablePath, EmbeddableDomainType<?> embeddableType) {
|
||||||
|
if ( !embeddableType.getPluralAttributes().isEmpty() ) {
|
||||||
|
throw new SemanticException( String.format(
|
||||||
|
"Explicit selection of an embeddable containing associated collections is not supported: %s",
|
||||||
|
navigablePath
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for ( SingularAttribute<?, ?> attribute : embeddableType.getSingularAttributes() ) {
|
||||||
|
if ( attribute.getType() instanceof EmbeddableDomainType<?> ) {
|
||||||
|
assertEmbeddableCollections( navigablePath, (EmbeddableDomainType<?>) attribute.getType() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendHqlString(StringBuilder sb) {
|
public void appendHqlString(StringBuilder sb) {
|
||||||
if ( selectClause != null ) {
|
if ( selectClause != null ) {
|
||||||
|
|
|
@ -6,10 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.sql.results.graph.embeddable.internal;
|
package org.hibernate.sql.results.graph.embeddable.internal;
|
||||||
|
|
||||||
import org.hibernate.metamodel.mapping.AttributeMapping;
|
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
|
||||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||||
import org.hibernate.query.SemanticException;
|
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||||
|
@ -47,10 +45,6 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
|
||||||
this.fetchContainer = modelPart.getEmbeddableTypeDescriptor();
|
this.fetchContainer = modelPart.getEmbeddableTypeDescriptor();
|
||||||
this.resultVariable = resultVariable;
|
this.resultVariable = resultVariable;
|
||||||
|
|
||||||
// We currently don't support explicitly selecting embeddables that contain collections
|
|
||||||
// as we wouldn't be able to correctly initialize their owning entity instances
|
|
||||||
checkContainsCollections( modelPart, navigablePath );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
An `{embeddable_result}` sub-path is created for the corresponding initializer to differentiate it from a fetch-initializer if this embedded is also fetched.
|
An `{embeddable_result}` sub-path is created for the corresponding initializer to differentiate it from a fetch-initializer if this embedded is also fetched.
|
||||||
The Jakarta Persistence spec says that any embedded value selected in the result should not be part of the state of any managed entity.
|
The Jakarta Persistence spec says that any embedded value selected in the result should not be part of the state of any managed entity.
|
||||||
|
@ -96,25 +90,6 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkContainsCollections(
|
|
||||||
EmbeddableValuedModelPart embeddableModelPart,
|
|
||||||
NavigablePath navigablePath) {
|
|
||||||
embeddableModelPart.forEachSubPart( (index, modelPart) -> {
|
|
||||||
final AttributeMapping attribute = modelPart.asAttributeMapping();
|
|
||||||
if ( attribute != null ) {
|
|
||||||
if ( attribute.isPluralAttributeMapping() ) {
|
|
||||||
throw new SemanticException( String.format(
|
|
||||||
"Explicit selection of an embeddable containing collections is not supported: %s",
|
|
||||||
navigablePath
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
else if ( attribute.isEmbeddedAttributeMapping() ) {
|
|
||||||
checkContainsCollections( attribute.asEmbeddedAttributeMapping(), navigablePath );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getResultVariable() {
|
public String getResultVariable() {
|
||||||
return resultVariable;
|
return resultVariable;
|
||||||
|
|
Loading…
Reference in New Issue