From eae3a4a0a62e1cc0ca0bc0aa4502ba5ebd212559 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Mon, 23 Mar 2020 08:28:56 -0500 Subject: [PATCH] fix issue with Criteria queries not defining selections explicitly. should use the (single) root as the selection. --- .../query/sqm/internal/QuerySqmImpl.java | 36 +++++++++++++++---- .../criteria/BasicCriteriaExecutionTests.java | 13 +++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java index b2057884bb..9c31d9014a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/QuerySqmImpl.java @@ -51,8 +51,10 @@ import org.hibernate.query.sqm.tree.SqmDmlStatement; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.expression.SqmParameter; +import org.hibernate.query.sqm.tree.from.SqmRoot; import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement; import org.hibernate.query.sqm.tree.insert.SqmInsertStatement; +import org.hibernate.query.sqm.tree.select.SqmQuerySpec; import org.hibernate.query.sqm.tree.select.SqmSelectStatement; import org.hibernate.query.sqm.tree.select.SqmSelection; import org.hibernate.query.sqm.tree.update.SqmUpdateStatement; @@ -178,15 +180,35 @@ public class QuerySqmImpl SharedSessionContractImplementor producer) { super( producer ); - if ( resultType != null ) { - if ( sqmStatement instanceof SqmSelectStatement ) { - //noinspection unchecked + if ( sqmStatement instanceof SqmSelectStatement ) { + final SqmSelectStatement sqmSelectStatement = (SqmSelectStatement) sqmStatement; + final SqmQuerySpec sqmQuerySpec = sqmSelectStatement.getQuerySpec(); + final List sqmSelections = sqmQuerySpec.getSelectClause().getSelections(); + + // make sure there is at least one root + final List sqmRoots = sqmQuerySpec.getFromClause().getRoots(); + if ( sqmRoots == null || sqmRoots.isEmpty() ) { + throw new IllegalArgumentException( "Criteria did not define any query roots" ); + } + + if ( sqmSelections == null || sqmSelections.isEmpty() ) { + // if there is a single root, use that as the selection + if ( sqmRoots.size() == 1 ) { + final SqmRoot sqmRoot = sqmRoots.get( 0 ); + sqmQuerySpec.getSelectClause().add( sqmRoot, null ); + } + else { + throw new IllegalArgumentException( ); + } + } + + if ( resultType != null ) { checkQueryReturnType( (SqmSelectStatement) sqmStatement, resultType, producer.getFactory() ); } - else { - assert sqmStatement instanceof SqmDmlStatement; - throw new IllegalArgumentException( "Non-select queries cannot be typed" ); - } + } + else { + assert sqmStatement instanceof SqmDmlStatement; + throw new IllegalArgumentException( "Non-select queries cannot be typed" ); } this.hqlString = ""; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/BasicCriteriaExecutionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/BasicCriteriaExecutionTests.java index 34ba03f478..4279b3287a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/BasicCriteriaExecutionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/BasicCriteriaExecutionTests.java @@ -16,6 +16,7 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.ParameterExpression; import javax.persistence.criteria.Root; +import org.hibernate.IrrelevantEntity; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaRoot; @@ -51,6 +52,18 @@ public class BasicCriteriaExecutionTests extends BaseNonConfigCoreFunctionalTest ); } + @Test + public void testIt() { + inSession( + session -> { + CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); + CriteriaQuery criteria = criteriaBuilder.createQuery( BasicEntity.class ); + criteria.from( BasicEntity.class ); + List results = session.createQuery( criteria ).list(); + } + ); + } + @Test public void testExecutingBasicCriteriaQueryInStatelessSession() { final CriteriaBuilder criteriaBuilder = sessionFactory().getCriteriaBuilder();