From 200e3830cb3eb63b6fef652055db0e105cc47ccd Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 18 Sep 2024 10:31:54 +0200 Subject: [PATCH 1/2] HHH-18628 Add test for issue --- .../CriteriaSelectOneToOneUnownedTest.java | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CriteriaSelectOneToOneUnownedTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CriteriaSelectOneToOneUnownedTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CriteriaSelectOneToOneUnownedTest.java new file mode 100644 index 000000000000..cf086f3e7b3e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CriteriaSelectOneToOneUnownedTest.java @@ -0,0 +1,138 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.jpa.criteria; + +import java.util.List; + +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Root; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@Jpa( + annotatedClasses = { + CriteriaSelectOneToOneUnownedTest.Parent.class, + CriteriaSelectOneToOneUnownedTest.Child.class, + } +) +@JiraKey("HHH-18628") +public class CriteriaSelectOneToOneUnownedTest { + + @BeforeEach + public void setUp(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + Child child = new Child( 1l, "child" ); + Parent parent = new Parent( 1l, "parent", child ); + entityManager.persist( parent ); + } + ); + } + + @AfterEach + public void tearDown(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + entityManager.createQuery( "delete from Child" ).executeUpdate(); + entityManager.createQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testCriteriaInnerJoin(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery query = cb.createQuery( Child.class ); + Root parent = query.from( Parent.class ); + Join child = parent.join( "child", JoinType.INNER ); + query.select( child ); + + List children = entityManager.createQuery( query ).getResultList(); + assertThat( children ).isNotNull(); + assertThat( children.size() ).isEqualTo( 1 ); + Child c = children.get( 0 ); + assertThat( c ).isNotNull(); + } ); + } + + @Test + public void testCriteriaLeftJoin(EntityManagerFactoryScope scope) { + scope.inTransaction( + entityManager -> { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + + CriteriaQuery query = cb.createQuery( Child.class ); + Root parent = query.from( Parent.class ); + Join child = parent.join( "child", JoinType.LEFT ); + query.select( child ); + + List children = entityManager.createQuery( query ).getResultList(); + assertThat( children ).isNotNull(); + assertThat( children.size() ).isEqualTo( 1 ); + Child c = children.get( 0 ); + assertThat( c ).isNotNull(); + } ); + } + + @Entity(name = "Parent") + public static class Parent { + @Id + private Long id; + + private String name; + + @OneToOne(mappedBy = "parent", cascade = CascadeType.PERSIST) + private Child child; + + public Parent() { + } + + public Parent(Long id, String name, Child child) { + this.id = id; + this.name = name; + this.child = child; + child.parent = this; + } + } + + @Entity(name = "Child") + public static class Child { + + @Id + private Long id; + + private String name; + + @OneToOne(optional = false, fetch = FetchType.LAZY) + private Parent parent; + + public Child() { + } + + public Child(Long id, String name) { + this.id = id; + this.name = name; + } + } + +} From 3ba88bd3601dea7d00eb586d641d9ec0f4df3cd4 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 18 Sep 2024 11:24:14 +0200 Subject: [PATCH 2/2] HHH-18628 Regression: Unable to determine TableReference --- .../src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4f3ad17bc7ee..3ecb7594f9fb 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 @@ -254,7 +254,7 @@ public static boolean isFkOptimizationAllowed(SqmPath sqmPath) { * or one that has an explicit on clause predicate. */ public static boolean isFkOptimizationAllowed(SqmPath sqmPath, EntityAssociationMapping associationMapping) { - if ( sqmPath instanceof SqmJoin ) { + if ( associationMapping.isFkOptimizationAllowed() && sqmPath instanceof SqmJoin ) { final SqmJoin sqmJoin = (SqmJoin) sqmPath; switch ( sqmJoin.getSqmJoinType() ) { case LEFT: