Skip to content

Commit 6bb8d03

Browse files
committed
HHH-9637 : Join is reused when 2 explicit joins are used for the same ToOne association
1 parent ce54660 commit 6bb8d03

File tree

14 files changed

+984
-3
lines changed

14 files changed

+984
-3
lines changed

hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/DotNode.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ private void dereferenceEntityJoin(String classAlias, EntityType propertyType, b
468468

469469
boolean found = elem != null;
470470
// even though we might find a pre-existing element by join path, we may not be able to reuse it...
471-
boolean useFoundFromElement = found && canReuse( elem );
471+
boolean useFoundFromElement = found && canReuse( classAlias, elem );
472472

473473
if ( !useFoundFromElement ) {
474474
// If this is an implied join in a from element, then use the impled join type which is part of the
@@ -517,16 +517,22 @@ private void dereferenceEntityJoin(String classAlias, EntityType propertyType, b
517517
setFromElement( elem ); // This 'dot' expression now refers to the resulting from element.
518518
}
519519

520-
private boolean canReuse(FromElement fromElement) {
520+
private boolean canReuse(String classAlias, FromElement fromElement) {
521521
// if the from-clauses are the same, we can be a little more aggressive in terms of what we reuse
522-
if ( fromElement.getFromClause() == getWalker().getCurrentFromClause() ) {
522+
if ( fromElement.getFromClause() == getWalker().getCurrentFromClause() &&
523+
areSame( classAlias, fromElement.getClassAlias() )) {
523524
return true;
524525
}
525526

526527
// otherwise (subquery case) dont reuse the fromElement if we are processing the from-clause of the subquery
527528
return getWalker().getCurrentClauseType() != SqlTokenTypes.FROM;
528529
}
529530

531+
private boolean areSame(String alias1, String alias2) {
532+
// again, null != null here
533+
return !StringHelper.isEmpty( alias1 ) && !StringHelper.isEmpty( alias2 ) && alias1.equals( alias2 );
534+
}
535+
530536
private void setImpliedJoin(FromElement elem) {
531537
this.impliedJoin = elem;
532538
if ( getFirstChild().getType() == SqlTokenTypes.DOT ) {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.test.hql.fetchAndJoin;
25+
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
import javax.persistence.CascadeType;
29+
import javax.persistence.Entity;
30+
import javax.persistence.FetchType;
31+
import javax.persistence.GeneratedValue;
32+
import javax.persistence.Id;
33+
import javax.persistence.JoinColumn;
34+
import javax.persistence.OneToMany;
35+
import javax.persistence.Table;
36+
37+
@Entity
38+
@Table(name = "entity1")
39+
public class Child {
40+
@Id
41+
@GeneratedValue
42+
private long id;
43+
44+
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
45+
@JoinColumn
46+
private Set<GrandChild> grandChildren = new HashSet<GrandChild>();
47+
48+
public Child() {
49+
}
50+
51+
public Child(String value) {
52+
this.value = value;
53+
}
54+
55+
private String value;
56+
57+
public long getId() {
58+
return id;
59+
}
60+
61+
public void setId(long id) {
62+
this.id = id;
63+
}
64+
65+
public Set<GrandChild> getGrandChildren() {
66+
return grandChildren;
67+
}
68+
69+
public void setGrandChildren(Set<GrandChild> grandChildren) {
70+
this.grandChildren = grandChildren;
71+
}
72+
73+
public String getValue() {
74+
return value;
75+
}
76+
77+
public void setValue(String value) {
78+
this.value = value;
79+
}
80+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.test.hql.fetchAndJoin;
25+
26+
import javax.persistence.Entity;
27+
import javax.persistence.GeneratedValue;
28+
import javax.persistence.Id;
29+
import javax.persistence.JoinColumn;
30+
import javax.persistence.ManyToOne;
31+
import javax.persistence.Table;
32+
33+
@Entity
34+
@Table(name = "entity1")
35+
public class Entity1 {
36+
@Id
37+
@GeneratedValue
38+
private long id;
39+
40+
@ManyToOne
41+
@JoinColumn(name="entity2_id", nullable = false)
42+
private Entity2 entity2;
43+
44+
private String value;
45+
46+
public long getId() {
47+
return id;
48+
}
49+
50+
public void setId(long id) {
51+
this.id = id;
52+
}
53+
54+
public Entity2 getEntity2() {
55+
return entity2;
56+
}
57+
58+
public void setEntity2(Entity2 entity2) {
59+
this.entity2 = entity2;
60+
}
61+
62+
public String getValue() {
63+
return value;
64+
}
65+
66+
public void setValue(String value) {
67+
this.value = value;
68+
}
69+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.test.hql.fetchAndJoin;
25+
26+
import javax.persistence.Entity;
27+
import javax.persistence.FetchType;
28+
import javax.persistence.GeneratedValue;
29+
import javax.persistence.Id;
30+
import javax.persistence.JoinColumn;
31+
import javax.persistence.ManyToOne;
32+
import javax.persistence.Table;
33+
34+
@Entity
35+
@Table(name = "entity2")
36+
public class Entity2 {
37+
@Id
38+
@GeneratedValue
39+
private long id;
40+
41+
@ManyToOne(fetch = FetchType.LAZY)
42+
@JoinColumn(name="entity3_id")
43+
private Entity3 entity3;
44+
45+
private String value;
46+
47+
public long getId() {
48+
return id;
49+
}
50+
51+
public void setId(long id) {
52+
this.id = id;
53+
}
54+
55+
public Entity3 getEntity3() {
56+
return entity3;
57+
}
58+
59+
public void setEntity3(Entity3 entity3) {
60+
this.entity3 = entity3;
61+
}
62+
63+
public String getValue() {
64+
return value;
65+
}
66+
67+
public void setValue(String value) {
68+
this.value = value;
69+
}
70+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.test.hql.fetchAndJoin;
25+
26+
import javax.persistence.Entity;
27+
import javax.persistence.GeneratedValue;
28+
import javax.persistence.Id;
29+
import javax.persistence.Table;
30+
31+
@Entity
32+
@Table(name = "entity3")
33+
public class Entity3 {
34+
@Id
35+
@GeneratedValue
36+
private long id;
37+
38+
private String value;
39+
40+
public long getId() {
41+
return id;
42+
}
43+
44+
public void setId(long id) {
45+
this.id = id;
46+
}
47+
48+
public String getValue() {
49+
return value;
50+
}
51+
52+
public void setValue(String value) {
53+
this.value = value;
54+
}
55+
56+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
5+
* indicated by the @author tags or express copyright attribution
6+
* statements applied by the authors. All third-party contributions are
7+
* distributed under license by Red Hat Inc.
8+
*
9+
* This copyrighted material is made available to anyone wishing to use, modify,
10+
* copy, or redistribute it subject to the terms and conditions of the GNU
11+
* Lesser General Public License, as published by the Free Software Foundation.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16+
* for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with this distribution; if not, write to:
20+
* Free Software Foundation, Inc.
21+
* 51 Franklin Street, Fifth Floor
22+
* Boston, MA 02110-1301 USA
23+
*/
24+
package org.hibernate.test.hql.fetchAndJoin;
25+
26+
import javax.persistence.Entity;
27+
import javax.persistence.FetchType;
28+
import javax.persistence.GeneratedValue;
29+
import javax.persistence.Id;
30+
import javax.persistence.JoinColumn;
31+
import javax.persistence.OneToMany;
32+
import javax.persistence.Table;
33+
34+
@Entity
35+
@Table(name = "entity1")
36+
public class GrandChild {
37+
@Id
38+
@GeneratedValue
39+
private long id;
40+
41+
private String value;
42+
43+
public GrandChild() {
44+
}
45+
46+
public GrandChild(String value) {
47+
this.value = value;
48+
}
49+
50+
public long getId() {
51+
return id;
52+
}
53+
54+
public void setId(long id) {
55+
this.id = id;
56+
}
57+
58+
public String getValue() {
59+
return value;
60+
}
61+
62+
public void setValue(String value) {
63+
this.value = value;
64+
}
65+
}

0 commit comments

Comments
 (0)