diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryJoinTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryJoinTest.java new file mode 100644 index 0000000000..4aae7286ac --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/SubqueryJoinTest.java @@ -0,0 +1,134 @@ +package org.hibernate.orm.test.query.criteria; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; +import jakarta.validation.constraints.NotNull; + +@Jpa( + annotatedClasses = { + SubqueryJoinTest.TestContext.class, + SubqueryJoinTest.TestUser.class, + } +) +public class SubqueryJoinTest { + + @Test + @TestForIssue(jiraKey = "HHH-15260") + public void subqueryJoinTest(EntityManagerFactoryScope scope) { + scope.inEntityManager( + entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + final CriteriaQuery c = cb.createQuery( TestContext.class ); + final Root from = c.from( TestContext.class ); + from.join( "user" ); + + final Subquery subQuery = c.subquery( TestUser.TestMarker.class ); + final Root sRoot = subQuery.from( TestUser.class ); + final Join join = sRoot.join( "markers" ); + subQuery.where( cb.equal( sRoot.get( "id" ), from.get( "user" ).get( "id" ) ) ); + subQuery.select( join ); + c.where( cb.exists( subQuery ).not() ); + + entityManager.createQuery( c ).getResultList(); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-15260") + public void subqueryJoinTest2(EntityManagerFactoryScope scope) { + scope.inEntityManager( + entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + final CriteriaQuery c = cb.createQuery( TestContext.class ); + final Root from = c.from( TestContext.class ); + from.join( "user" ).join( "context" ); + + final Subquery subQuery = c.subquery( TestUser.TestMarker.class ); + final Root sRoot = subQuery.from( TestUser.class ); + final Join join = sRoot.join( "markers" ); + sRoot.join( "context" ); + subQuery.where( cb.equal( sRoot.get( "id" ), from.get( "user" ).get( "context" ).get( "user" ).get( "id" ) ) ); + subQuery.select( join ); + c.where( cb.exists( subQuery ).not() ); + + entityManager.createQuery( c ).getResultList(); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-15260") + public void subqueryJoinTest3(EntityManagerFactoryScope scope) { + scope.inEntityManager( + entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + final CriteriaQuery c = cb.createQuery( TestContext.class ); + final Root from = c.from( TestContext.class ); + from.join( "user" ).join( "context" ); + + final Subquery subQuery = c.subquery( TestUser.TestMarker.class ); + final Root sRoot = subQuery.from( TestUser.class ); + final Join join = sRoot.join( "markers" ); + sRoot.join( "context" ); + subQuery.where( cb.equal( sRoot.get( "id" ), from.get( "user" ).get( "context" ).get( "id" ) ) ); + subQuery.select( join ); + c.where( cb.exists( subQuery ).not() ); + + entityManager.createQuery( c ).getResultList(); + } + ); + } + + @Entity(name = "TestContext") + public static class TestContext { + + @Id + private Integer id; + + @NotNull + @OneToOne(optional = false) + private TestUser user; + + } + + @Entity(name = "TestUser") + public static class TestUser { + + @Id + private Integer id; + + @ManyToOne + private TestContext context; + + @ElementCollection + @Enumerated(EnumType.STRING) + private List markers = new ArrayList<>(); + + public enum TestMarker { + TEST + } + } + +}