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 29d884b188..fd0492fd27 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 @@ -127,6 +127,10 @@ public class SqmSubQuery extends AbstractSqmSelectQuery implements SqmSele @Override public SqmExpression getSelection() { + final SqmSelectClause selectClause = getQuerySpec().getSelectClause(); + if ( selectClause == null ) { + return null; + } return this; } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/RootEntityTypeModelTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/RootEntityTypeModelTest.java index 20a14925ca..a85f35f03a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/RootEntityTypeModelTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/RootEntityTypeModelTest.java @@ -1,3 +1,9 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later + * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html + */ package org.hibernate.orm.test.query.criteria; import org.hibernate.testing.orm.junit.DomainModel; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryGroupByTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryGroupByTest.java new file mode 100644 index 0000000000..deea9122b8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryGroupByTest.java @@ -0,0 +1,145 @@ +package org.hibernate.orm.test.query.criteria; + +import java.util.List; + +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +@Jpa( + annotatedClasses = { + SubqueryGroupByTest.JobTile.class, + SubqueryGroupByTest.Person.class, + } +) +public class SubqueryGroupByTest { + + @BeforeEach + public void setUp(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + JobTile worker = new JobTile( 1, "Worker" ); + JobTile plumber = new JobTile( 2, "Plumber" ); + Person p1 = new Person( 1, "Luigi", worker ); + Person p2 = new Person( 2, "Andrea", plumber ); + + entityManager.persist( worker ); + entityManager.persist( plumber ); + entityManager.persist( p1 ); + entityManager.persist( p2 ); + } + ); + } + + @Test + public void subqueryGroupTest(EntityManagerFactoryScope scope) { + + scope.inEntityManager( + entityManager -> { + final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery( Person.class ); + final Root person = criteriaQuery.from( Person.class ); + + criteriaQuery.select( person ); + + final Subquery subquery = criteriaQuery.subquery( String.class ); + assertEquals( 0, subquery.getGroupList().size() ); + + assertNull( subquery.getSelection() ); + + final Root jobTitle = subquery.from( JobTile.class ); + subquery.select( jobTitle.get( "name" ) ); + assertNotNull( subquery.getSelection() ); + + subquery.where( criteriaBuilder.equal( jobTitle.get( "name" ), "Worker" ) ); + + subquery.groupBy( jobTitle.get( "name" ) ); + assertEquals( 1, subquery.getGroupList().size() ); + + criteriaQuery.where( person.get( "jobTile" ).get( "name" ).in( subquery ) ); + + List result = entityManager.createQuery( criteriaQuery ).getResultList(); + + assertEquals( 1, result.size() ); + assertEquals( "Luigi", result.get( 0 ).getName() ); + + } + ); + } + + @Entity(name = "Person") + @Table(name = "PERSON_TABLE") + public static class Person { + + @Id + private Integer id; + + private String name; + + @ManyToOne + private JobTile jobTile; + + public Person() { + } + + public Person(Integer id, String name, JobTile jobTile) { + this.id = id; + this.name = name; + this.jobTile = jobTile; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + public JobTile getJobTile() { + return jobTile; + } + } + + @Entity(name = "JobTile") + @Table(name = "JOBTITLE_TABLE") + public static class JobTile { + + @Id + private Integer id; + + private String name; + + public JobTile() { + } + + public JobTile(Integer id, String name) { + this.id = id; + this.name = name; + } + + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + } + +}