Skip to content

Commit a36393b

Browse files
committed
HHH-17670 Test and fix for NPE in FromClause#findTableGroup
1 parent 186bcc6 commit a36393b

File tree

2 files changed

+113
-1
lines changed

2 files changed

+113
-1
lines changed

hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/FromClause.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public TableGroup findTableGroup(NavigablePath navigablePath) {
232232
if ( navigablePath.equals( tg.getNavigablePath() ) ) {
233233
return tg;
234234
}
235-
if ( tg instanceof OneToManyTableGroup && navigablePath.getParent().equals( tg.getNavigablePath() ) ) {
235+
if ( tg instanceof OneToManyTableGroup && tg.getNavigablePath().equals( navigablePath.getParent() ) ) {
236236
return ( (OneToManyTableGroup) tg ).getTableGroup( CollectionPart.Nature.fromName( navigablePath.getLocalName() ) );
237237
}
238238
return null;
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package org.hibernate.orm.test.batch;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.hibernate.annotations.Fetch;
7+
import org.hibernate.annotations.FetchMode;
8+
import org.hibernate.cfg.AvailableSettings;
9+
10+
import org.hibernate.testing.orm.junit.DomainModel;
11+
import org.hibernate.testing.orm.junit.JiraKey;
12+
import org.hibernate.testing.orm.junit.ServiceRegistry;
13+
import org.hibernate.testing.orm.junit.SessionFactory;
14+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
15+
import org.hibernate.testing.orm.junit.Setting;
16+
import org.junit.jupiter.api.BeforeAll;
17+
import org.junit.jupiter.api.Test;
18+
19+
import jakarta.persistence.Entity;
20+
import jakarta.persistence.Id;
21+
import jakarta.persistence.ManyToOne;
22+
import jakarta.persistence.OneToMany;
23+
24+
@DomainModel(
25+
annotatedClasses = {
26+
BatchSubselectCollection3Test.SimpleA.class,
27+
BatchSubselectCollection3Test.SimpleB.class,
28+
BatchSubselectCollection3Test.SimpleC.class,
29+
BatchSubselectCollection3Test.SimpleD.class
30+
}
31+
)
32+
@SessionFactory
33+
@ServiceRegistry(
34+
settings = {
35+
@Setting(name = AvailableSettings.DEFAULT_BATCH_FETCH_SIZE, value = "10"),
36+
@Setting(name = AvailableSettings.FORMAT_SQL, value = "false"),
37+
}
38+
)
39+
@JiraKey("HHH-17670")
40+
public class BatchSubselectCollection3Test {
41+
42+
@BeforeAll
43+
public void setUp(SessionFactoryScope scope) {
44+
scope.inTransaction(
45+
session -> {
46+
session.persist( new SimpleA( 1L ) );
47+
session.persist( new SimpleA( 2L ) );
48+
49+
session.persist( new SimpleC( 1L ) );
50+
session.persist( new SimpleC( 2L ) );
51+
}
52+
);
53+
}
54+
55+
@Test
56+
public void testQuery(SessionFactoryScope scope) {
57+
scope.inTransaction(
58+
session -> {
59+
// To trigger the NPE, it is vital to have a OneToManyTableGroup before the table group that is selected
60+
session.createQuery( "select obj2 from SimpleA obj left outer join obj.children obj1, SimpleC obj2" )
61+
.getResultList();
62+
}
63+
);
64+
}
65+
66+
@Entity(name = "SimpleA")
67+
public static class SimpleA {
68+
@Id
69+
private Long id;
70+
@OneToMany(mappedBy = "parent")
71+
private List<SimpleB> children = new ArrayList<>();
72+
73+
public SimpleA() {
74+
}
75+
76+
public SimpleA(Long id) {
77+
this.id = id;
78+
}
79+
}
80+
81+
@Entity(name = "SimpleB")
82+
public static class SimpleB {
83+
@Id
84+
private Long id;
85+
@ManyToOne
86+
private SimpleA parent;
87+
}
88+
89+
@Entity(name = "SimpleC")
90+
public static class SimpleC {
91+
@Id
92+
private Long id;
93+
private String s;
94+
@OneToMany
95+
@Fetch(FetchMode.SUBSELECT)
96+
private List<SimpleD> children2 = new ArrayList<>();
97+
98+
public SimpleC() {
99+
}
100+
101+
public SimpleC(Long id) {
102+
this.id = id;
103+
}
104+
}
105+
106+
@Entity(name = "SimpleD")
107+
public static class SimpleD {
108+
@Id
109+
private Long id;
110+
private String s;
111+
}
112+
}

0 commit comments

Comments
 (0)