diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java index ba5d62901fa8..a17dbd78d7c3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashSet; @@ -17,6 +18,7 @@ import java.util.Set; import java.util.StringTokenizer; +import jakarta.persistence.criteria.ParameterExpression; import org.hibernate.AssertionFailure; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; @@ -74,6 +76,7 @@ import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.expression.SqmTuple; +import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter; import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmJoin; @@ -112,6 +115,8 @@ import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; +import static java.util.Collections.singleton; +import static java.util.Collections.unmodifiableSet; import static java.util.stream.Collectors.toList; import static org.hibernate.internal.util.NullnessUtil.castNonNull; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; @@ -1326,4 +1331,27 @@ private static void throwQueryTypeMismatchException( resultClass.getName() ) ); } + + public static Set> getParameters(SqmStatement statement) { + final Set> parameters = statement.getSqmParameters(); + return switch ( parameters.size() ) { + case 0 -> emptySet(); + case 1 -> { + final SqmParameter parameter = parameters.iterator().next(); + yield parameter instanceof ValueBindJpaCriteriaParameter + ? emptySet() + : singleton( parameter ); + } + default -> { + final Set> parameterExpressions = + new HashSet<>( parameters.size() ); + for ( SqmParameter parameter : parameters ) { + if ( !(parameter instanceof ValueBindJpaCriteriaParameter) ) { + parameterExpressions.add( parameter ); + } + } + yield unmodifiableSet( parameterExpressions ); + } + }; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/AbstractSqmStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/AbstractSqmStatement.java index b2306eeeb92d..3d401019e25f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/AbstractSqmStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/AbstractSqmStatement.java @@ -4,20 +4,19 @@ */ package org.hibernate.query.sqm.tree; -import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.stream.Collectors; import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.internal.ParameterCollector; import org.hibernate.query.sqm.internal.SqmUtil; import org.hibernate.query.sqm.tree.expression.SqmParameter; -import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter; import jakarta.persistence.criteria.ParameterExpression; +import static java.util.Collections.emptySet; +import static java.util.Collections.unmodifiableSet; import static org.hibernate.query.sqm.tree.jpa.ParameterCollector.collectParameters; /** @@ -66,7 +65,6 @@ public void addParameter(SqmParameter parameter) { if ( parameters == null ) { parameters = new HashSet<>(); } - parameters.add( parameter ); } @@ -76,8 +74,9 @@ public Set> getSqmParameters() { assert parameters == null : "SqmSelectStatement (as Criteria) should not have collected parameters"; return collectParameters( this ); } - - return parameters == null ? Collections.emptySet() : Collections.unmodifiableSet( parameters ); + else { + return parameters == null ? emptySet() : unmodifiableSet( parameters ); + } } @Override @@ -88,13 +87,9 @@ public ParameterResolutions resolveParameters() { @Override public Set> getParameters() { // At this level, the number of parameters may still be growing as - // nodes are added to the Criteria - so we re-calculate this every - // time. - // - // for a "finalized" set of parameters, use `#resolveParameters` instead - assert getQuerySource() == SqmQuerySource.CRITERIA; - return getSqmParameters().stream() - .filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) ) - .collect( Collectors.toSet() ); + // nodes are added to the Criteria, so we recalculate this every time. + // For a finalized set of parameters, use resolveParameters() instead + assert querySource == SqmQuerySource.CRITERIA; + return SqmUtil.getParameters( this ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertSelectStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertSelectStatement.java index 3afdf8164b93..6c4aba3e814a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertSelectStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertSelectStatement.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.hibernate.Incubating; import org.hibernate.query.criteria.JpaConflictClause; @@ -21,7 +20,6 @@ import org.hibernate.query.sqm.tree.cte.SqmCteStatement; import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.expression.SqmParameter; -import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter; import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.select.SqmQueryPart; import org.hibernate.query.sqm.tree.select.SqmQuerySpec; @@ -33,7 +31,6 @@ import jakarta.persistence.criteria.Path; import org.checkerframework.checker.nullness.qual.Nullable; -import jakarta.persistence.criteria.ParameterExpression; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.EntityType; @@ -147,19 +144,6 @@ public JpaPredicate getRestriction() { return null; } - @Override - public Set> getParameters() { - // At this level, the number of parameters may still be growing as - // nodes are added to the Criteria - so we re-calculate this every - // time. - // - // for a "finalized" set of parameters, use `#resolveParameters` instead - assert getQuerySource() == SqmQuerySource.CRITERIA; - return getSqmParameters().stream() - .filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) ) - .collect( Collectors.toSet() ); - } - @Override public SqmInsertSelectStatement setInsertionTargetPaths(Path... insertionTargetPaths) { super.setInsertionTargetPaths( insertionTargetPaths ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertValuesStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertValuesStatement.java index e13c1aa06cb8..53a0d4ec034a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertValuesStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/insert/SqmInsertValuesStatement.java @@ -10,7 +10,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import org.hibernate.query.criteria.JpaConflictClause; import org.hibernate.query.criteria.JpaCriteriaInsertValues; @@ -25,10 +24,8 @@ import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.expression.SqmExpression; import org.hibernate.query.sqm.tree.expression.SqmParameter; -import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter; import org.hibernate.query.sqm.tree.from.SqmRoot; -import jakarta.persistence.criteria.ParameterExpression; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.EntityType; @@ -154,19 +151,6 @@ public JpaPredicate getRestriction() { return null; } - @Override - public Set> getParameters() { - // At this level, the number of parameters may still be growing as - // nodes are added to the Criteria - so we re-calculate this every - // time. - // - // for a "finalized" set of parameters, use `#resolveParameters` instead - assert getQuerySource() == SqmQuerySource.CRITERIA; - return getSqmParameters().stream() - .filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) ) - .collect( Collectors.toSet() ); - } - @Override public SqmInsertValuesStatement setInsertionTargetPaths(Path... insertionTargetPaths) { super.setInsertionTargetPaths( insertionTargetPaths ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java index b272176e123b..965caa315b2f 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java @@ -254,8 +254,7 @@ public JpaRoot getRoot(int position, Class type) { * @see org.hibernate.query.criteria.JpaCriteriaQuery#getRoot(String, Class) */ public JpaRoot getRoot(String alias, Class type) { - final List> rootList = getQuerySpec().getRootList(); - for ( SqmRoot root : rootList ) { + for ( SqmRoot root : getQuerySpec().getRootList() ) { final String rootAlias = root.getAlias(); if ( rootAlias != null && rootAlias.equals( alias ) ) { return castRoot( root, type ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQuerySpec.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQuerySpec.java index d6b45f9dbba1..5d1f464f8e8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQuerySpec.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmQuerySpec.java @@ -295,9 +295,8 @@ public SqmQuerySpec setSelection(JpaSelection selection) { // NOTE : this call comes from JPA which inherently supports just a // single (possibly "compound") selection. // We have this special case where we return the SqmSelectClause itself if it doesn't have exactly 1 item - if ( selection instanceof SqmSelectClause ) { + if ( selection instanceof SqmSelectClause sqmSelectClause ) { if ( selection != selectClause ) { - final SqmSelectClause sqmSelectClause = (SqmSelectClause) selection; final List> selections = sqmSelectClause.getSelections(); selectClause.setSelection( selections.get( 0 ).getSelectableNode() ); for ( int i = 1; i < selections.size(); i++ ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java index 719f284716a5..59e708505c47 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java @@ -9,7 +9,6 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; import org.hibernate.Internal; import org.hibernate.query.criteria.JpaCriteriaQuery; @@ -25,7 +24,6 @@ import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.cte.SqmCteStatement; -import org.hibernate.query.sqm.tree.expression.ValueBindJpaCriteriaParameter; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.query.sqm.tree.from.SqmFromClause; import org.hibernate.query.sqm.tree.predicate.SqmPredicate; @@ -304,14 +302,10 @@ public SqmSelectStatement distinct(boolean distinct) { @Override public Set> getParameters() { // At this level, the number of parameters may still be growing as - // nodes are added to the Criteria - so we re-calculate this every - // time. - // - // for a "finalized" set of parameters, use `#resolveParameters` instead - assert querySource == CRITERIA; - return getSqmParameters().stream() - .filter( parameterExpression -> !( parameterExpression instanceof ValueBindJpaCriteriaParameter ) ) - .collect( Collectors.toSet() ); + // nodes are added to the Criteria, so we recalculate this every time. + // For a finalized set of parameters, use resolveParameters() instead + assert querySource == SqmQuerySource.CRITERIA; + return SqmUtil.getParameters( this ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java index d652376d4b49..2dbb73f9ca39 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java @@ -7,7 +7,6 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -76,6 +75,7 @@ import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.EntityType; +import static java.util.Collections.emptySet; import static org.hibernate.query.sqm.spi.SqmCreationHelper.combinePredicates; /** @@ -736,7 +736,7 @@ public Subquery having(List restrictions) { @Override public Set> getParameters() { - return Collections.emptySet(); + return emptySet(); } @Override