Skip to content

Commit f58d4a0

Browse files
committed
HHH-17706 Optimize FK comparison to eliminate unnecessary left join
Fix regression introduced by ef155c2
1 parent dc9a997 commit f58d4a0

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
* Helper utilities for dealing with SQM
8080
*
8181
* @author Steve Ebersole
82+
* @author Yanming Zhou
8283
*/
8384
public class SqmUtil {
8485
private SqmUtil() {
@@ -130,6 +131,9 @@ public static IllegalQueryOperationException expectingNonSelect(SqmStatement<?>
130131
* dereferenced using the target table mapping, i.e. when the path's lhs is an explicit join.
131132
*/
132133
public static boolean needsTargetTableMapping(SqmPath<?> sqmPath, ModelPartContainer modelPartContainer) {
134+
if ( isFkOptimizationAllowed(sqmPath.getLhs()) ) {
135+
return false;
136+
}
133137
return modelPartContainer.getPartMappingType() != modelPartContainer
134138
&& sqmPath.getLhs() instanceof SqmFrom<?, ?>
135139
&& modelPartContainer.getPartMappingType() instanceof ManagedMappingType;

hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ql/MapIssueTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ public void testMapKeyJoinIsIncluded(SessionFactoryScope scope) {
5959
s -> {
6060
s.createQuery( "select c from MapOwner as o join o.contents c join c.relationship r where r.id is not null" ).list();
6161
statementInspector.assertExecutedCount( 1 );
62-
// Assert 3 joins, collection table, collection element and relationship
63-
statementInspector.assertNumberOfJoins( 0, 3 );
62+
// Assert 2 joins, collection table, collection element
63+
statementInspector.assertNumberOfJoins( 0, 2 );
6464
}
6565
);
6666
}

hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/manytoone/ManyToOneTest.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
import jakarta.persistence.Entity;
1010
import jakarta.persistence.FetchType;
1111
import jakarta.persistence.Id;
12-
import jakarta.persistence.JoinColumn;
13-
import jakarta.persistence.JoinTable;
1412
import jakarta.persistence.ManyToOne;
1513
import jakarta.persistence.Table;
14+
import jakarta.persistence.criteria.CriteriaBuilder;
15+
import jakarta.persistence.criteria.CriteriaQuery;
16+
import jakarta.persistence.criteria.JoinType;
17+
import jakarta.persistence.criteria.Root;
1618

1719
import org.hibernate.Hibernate;
1820
import org.hibernate.stat.spi.StatisticsImplementor;
19-
21+
import org.hibernate.testing.jdbc.SQLStatementInspector;
2022
import org.hibernate.testing.orm.junit.DomainModel;
2123
import org.hibernate.testing.orm.junit.ServiceRegistry;
2224
import org.hibernate.testing.orm.junit.SessionFactory;
@@ -34,6 +36,7 @@
3436

3537
/**
3638
* @author Andrea Boriero
39+
* @author Yanming Zhou
3740
*/
3841
@DomainModel(
3942
annotatedClasses = {
@@ -304,6 +307,23 @@ public void testDelete(SessionFactoryScope scope) {
304307
);
305308
}
306309

310+
@Test
311+
public void testFkOptimizationWithLeftJoin(SessionFactoryScope scope) {
312+
SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
313+
statementInspector.clear();
314+
scope.inTransaction(
315+
session -> {
316+
CriteriaBuilder cb = session.getCriteriaBuilder();
317+
CriteriaQuery<OtherEntity> cq = cb.createQuery( OtherEntity.class );
318+
Root<OtherEntity> root = cq.from( OtherEntity.class );
319+
cq.select(root).where( cb.equal( root.join("simpleEntity", JoinType.LEFT ).get( "id" ), 1 ) );
320+
assertThat( session.createQuery( cq ).getResultList().size(), is(1) );
321+
statementInspector.assertExecutedCount( 1 );
322+
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 0 );
323+
}
324+
);
325+
}
326+
307327
@BeforeEach
308328
public void setUp(SessionFactoryScope scope) {
309329
scope.inTransaction(

hibernate-core/src/test/java/org/hibernate/orm/test/sql/exec/onetoone/bidirectional/EntityWithBidirectionalAssociationsOneOfWhichIsAJoinTableTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ public void testHqlSelectSon(SessionFactoryScope scope) {
153153

154154
statementInspector.assertExecutedCount( 2 );
155155
// The join to the target table PARENT for Male#parent is added since it's explicitly joined in HQL
156-
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 );
156+
statementInspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 );
157157
statementInspector.assertNumberOfOccurrenceInQuery( 1, "join", 3 );
158158
assertThat( son.getParent(), CoreMatchers.notNullValue() );
159159

0 commit comments

Comments
 (0)