HHH-9637 : Join is reused when 2 explicit joins are used for the same ToOne association
This commit is contained in:
parent
ce54660cdb
commit
6bb8d03595
|
@ -468,7 +468,7 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
|
||||
boolean found = elem != null;
|
||||
// even though we might find a pre-existing element by join path, we may not be able to reuse it...
|
||||
boolean useFoundFromElement = found && canReuse( elem );
|
||||
boolean useFoundFromElement = found && canReuse( classAlias, elem );
|
||||
|
||||
if ( !useFoundFromElement ) {
|
||||
// If this is an implied join in a from element, then use the impled join type which is part of the
|
||||
|
@ -517,9 +517,10 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
setFromElement( elem ); // This 'dot' expression now refers to the resulting from element.
|
||||
}
|
||||
|
||||
private boolean canReuse(FromElement fromElement) {
|
||||
private boolean canReuse(String classAlias, FromElement fromElement) {
|
||||
// if the from-clauses are the same, we can be a little more aggressive in terms of what we reuse
|
||||
if ( fromElement.getFromClause() == getWalker().getCurrentFromClause() ) {
|
||||
if ( fromElement.getFromClause() == getWalker().getCurrentFromClause() &&
|
||||
areSame( classAlias, fromElement.getClassAlias() )) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -527,6 +528,11 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
return getWalker().getCurrentClauseType() != SqlTokenTypes.FROM;
|
||||
}
|
||||
|
||||
private boolean areSame(String alias1, String alias2) {
|
||||
// again, null != null here
|
||||
return !StringHelper.isEmpty( alias1 ) && !StringHelper.isEmpty( alias2 ) && alias1.equals( alias2 );
|
||||
}
|
||||
|
||||
private void setImpliedJoin(FromElement elem) {
|
||||
this.impliedJoin = elem;
|
||||
if ( getFirstChild().getType() == SqlTokenTypes.DOT ) {
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity1")
|
||||
public class Child {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@JoinColumn
|
||||
private Set<GrandChild> grandChildren = new HashSet<GrandChild>();
|
||||
|
||||
public Child() {
|
||||
}
|
||||
|
||||
public Child(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private String value;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<GrandChild> getGrandChildren() {
|
||||
return grandChildren;
|
||||
}
|
||||
|
||||
public void setGrandChildren(Set<GrandChild> grandChildren) {
|
||||
this.grandChildren = grandChildren;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity1")
|
||||
public class Entity1 {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="entity2_id", nullable = false)
|
||||
private Entity2 entity2;
|
||||
|
||||
private String value;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Entity2 getEntity2() {
|
||||
return entity2;
|
||||
}
|
||||
|
||||
public void setEntity2(Entity2 entity2) {
|
||||
this.entity2 = entity2;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity2")
|
||||
public class Entity2 {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="entity3_id")
|
||||
private Entity3 entity3;
|
||||
|
||||
private String value;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Entity3 getEntity3() {
|
||||
return entity3;
|
||||
}
|
||||
|
||||
public void setEntity3(Entity3 entity3) {
|
||||
this.entity3 = entity3;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity3")
|
||||
public class Entity3 {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
private String value;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity1")
|
||||
public class GrandChild {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
private String value;
|
||||
|
||||
public GrandChild() {
|
||||
}
|
||||
|
||||
public GrandChild(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity1")
|
||||
public class Parent {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private long id;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
|
||||
@JoinColumn
|
||||
private Set<Child> children = new HashSet<Child>();
|
||||
|
||||
private String value;
|
||||
|
||||
public Parent() {
|
||||
}
|
||||
|
||||
public Parent(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Child> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(Set<Child> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ToManyFetchAndJoinTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
Parent p = new Parent( "p" );
|
||||
Child c1 = new Child( "c1" );
|
||||
GrandChild gc11 = new GrandChild( "gc11" );
|
||||
GrandChild gc12 = new GrandChild( "gc12" );
|
||||
p.getChildren().add( c1 );
|
||||
c1.getGrandChildren().add( gc11 );
|
||||
c1.getGrandChildren().add( gc12 );
|
||||
|
||||
Child c2 = new Child( "c2" );
|
||||
GrandChild gc21 = new GrandChild( "gc21" );
|
||||
GrandChild gc22 = new GrandChild( "gc22" );
|
||||
GrandChild gc23 = new GrandChild( "gc23" );
|
||||
p.getChildren().add( c2 );
|
||||
c2.getGrandChildren().add( gc21 );
|
||||
c2.getGrandChildren().add( gc22 );
|
||||
c2.getGrandChildren().add( gc23 );
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( p );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.createQuery( "delete Parent" ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinBeforeFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Parent p =
|
||||
(Parent) s.createQuery(
|
||||
"select p from Parent p inner join p.children cRestrict inner join fetch p.children c inner join fetch c.grandChildren where cRestrict.value = 'c1'" )
|
||||
.uniqueResult();
|
||||
|
||||
assertEquals( "p", p.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( p.getChildren() ) );
|
||||
assertEquals( 2, p.getChildren().size() );
|
||||
Iterator<Child> iterator = p.getChildren().iterator();
|
||||
Child cA = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cA.getGrandChildren() ) );
|
||||
if ( cA.getValue().equals( "c1" ) ) {
|
||||
assertEquals( 2, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 3, cB.getGrandChildren().size() );
|
||||
}
|
||||
else if ( cA.getValue().equals( "c2" ) ) {
|
||||
assertEquals( 3, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 2, cB.getGrandChildren().size() );
|
||||
}
|
||||
else {
|
||||
fail( "unexpected value" );
|
||||
}
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinBetweenFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Parent p =
|
||||
(Parent) s.createQuery(
|
||||
"select p from Parent p inner join fetch p.children c inner join p.children cRestrict inner join fetch c.grandChildren where cRestrict.value = 'c1'" )
|
||||
.uniqueResult();
|
||||
|
||||
assertEquals( "p", p.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( p.getChildren() ) );
|
||||
assertEquals( 2, p.getChildren().size() );
|
||||
Iterator<Child> iterator = p.getChildren().iterator();
|
||||
Child cA = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cA.getGrandChildren() ) );
|
||||
if ( cA.getValue().equals( "c1" ) ) {
|
||||
assertEquals( 2, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 3, cB.getGrandChildren().size() );
|
||||
}
|
||||
else if ( cA.getValue().equals( "c2" ) ) {
|
||||
assertEquals( 3, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 2, cB.getGrandChildren().size() );
|
||||
}
|
||||
else {
|
||||
fail( "unexpected value" );
|
||||
}
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinAfterFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Parent p =
|
||||
(Parent) s.createQuery(
|
||||
"select p from Parent p inner join fetch p.children c inner join fetch c.grandChildren inner join p.children cRestrict where cRestrict.value = 'c1'" )
|
||||
.uniqueResult();
|
||||
|
||||
assertEquals( "p", p.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( p.getChildren() ) );
|
||||
assertEquals( 2, p.getChildren().size() );
|
||||
Iterator<Child> iterator = p.getChildren().iterator();
|
||||
Child cA = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cA.getGrandChildren() ) );
|
||||
if ( cA.getValue().equals( "c1" ) ) {
|
||||
assertEquals( 2, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 3, cB.getGrandChildren().size() );
|
||||
}
|
||||
else if ( cA.getValue().equals( "c2" ) ) {
|
||||
assertEquals( 3, cA.getGrandChildren().size() );
|
||||
Child cB = iterator.next();
|
||||
assertTrue( Hibernate.isInitialized( cB.getGrandChildren() ) );
|
||||
assertEquals( 2, cB.getGrandChildren().size() );
|
||||
}
|
||||
else {
|
||||
fail( "unexpected value" );
|
||||
}
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
Parent.class,
|
||||
Child.class,
|
||||
GrandChild.class
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.hql.fetchAndJoin;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class ToOneFetchAndJoinTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
Entity1 e1 = new Entity1();
|
||||
e1.setValue( "entity1" );
|
||||
Entity2 e2 = new Entity2();
|
||||
e2.setValue( "entity2" );
|
||||
Entity3 e3 = new Entity3();
|
||||
e3.setValue( "entity3" );
|
||||
|
||||
e1.setEntity2( e2 );
|
||||
e2.setEntity3( e3 );
|
||||
|
||||
Entity2 e2a = new Entity2();
|
||||
e2a.setValue( "entity2a" );
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.persist( e3 );
|
||||
s.persist( e2 );
|
||||
s.persist( e1 );
|
||||
s.persist( e2a );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
s.createQuery( "delete Entity1" ).executeUpdate();
|
||||
s.createQuery( "delete Entity2" ).executeUpdate();
|
||||
s.createQuery( "delete Entity3" ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testFetchJoinsWithImplicitJoinInRestriction() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Entity1 e1Queryied =
|
||||
(Entity1) s.createQuery(
|
||||
"select e1 from Entity1 e1 inner join fetch e1.entity2 e2 inner join fetch e2.entity3 where e1.entity2.value = 'entity2'" )
|
||||
.uniqueResult();
|
||||
assertEquals( "entity1", e1Queryied.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2() ) );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2().getEntity3() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinBeforeFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Entity1 e1Queryied =
|
||||
(Entity1) s.createQuery(
|
||||
"select e1 from Entity1 e1 inner join e1.entity2 e1Restrict inner join fetch e1.entity2 e2 inner join fetch e2.entity3 where e1Restrict.value = 'entity2'" )
|
||||
.uniqueResult();
|
||||
assertEquals( "entity1", e1Queryied.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2() ) );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2().getEntity3() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinBetweenFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Entity1 e1Queryied =
|
||||
(Entity1) s.createQuery(
|
||||
"select e1 from Entity1 e1 inner join fetch e1.entity2 e2 inner join e1.entity2 e1Restrict inner join fetch e2.entity3 where e1Restrict.value = 'entity2'" )
|
||||
.uniqueResult();
|
||||
assertEquals( "entity1", e1Queryied.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2() ) );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2().getEntity3() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9637")
|
||||
public void testExplicitJoinAfterFetchJoins() {
|
||||
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Entity1 e1Queryied =
|
||||
(Entity1) s.createQuery(
|
||||
"select e1 from Entity1 e1 inner join fetch e1.entity2 e2 inner join fetch e2.entity3 inner join e1.entity2 e1Restrict where e1Restrict.value = 'entity2'" )
|
||||
.uniqueResult();
|
||||
assertEquals( "entity1", e1Queryied.getValue() );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2() ) );
|
||||
assertTrue( Hibernate.isInitialized( e1Queryied.getEntity2().getEntity3() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[]{
|
||||
Entity1.class,
|
||||
Entity2.class,
|
||||
Entity3.class
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.test.criteria.paths;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Fetch;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
|
||||
import org.hibernate.jpa.test.metamodel.Entity1;
|
||||
import org.hibernate.jpa.test.metamodel.Entity1_;
|
||||
import org.hibernate.jpa.test.metamodel.Entity2;
|
||||
import org.hibernate.jpa.test.metamodel.Entity2_;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class FetchAndJoinTest extends AbstractMetamodelSpecificTest {
|
||||
|
||||
@Test
|
||||
public void testImplicitJoinFromExplicitCollectionJoin() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
final CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
final CriteriaQuery<Entity1> criteria = builder.createQuery(Entity1.class);
|
||||
|
||||
final Root<Entity1> root = criteria.from(Entity1.class);
|
||||
final Join<Entity1, Entity2> entity2Join = root.join( Entity1_.entity2, JoinType.INNER); // illegal with fetch join
|
||||
|
||||
final Fetch<Entity1, Entity2> entity2Fetch = root.fetch(Entity1_.entity2, JoinType.INNER); // <=== REMOVE
|
||||
entity2Fetch.fetch( Entity2_.entity3 ); // <=== REMOVE
|
||||
|
||||
criteria.where(builder.equal(root.get(Entity1_.value), "test"),
|
||||
builder.equal(entity2Join.get(Entity2_.value), "test")); // illegal with fetch join
|
||||
|
||||
em.createQuery(criteria).getResultList();
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ public abstract class AbstractMetamodelSpecificTest extends BaseEntityManagerFun
|
|||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Address.class, Alias.class, Country.class, CreditCard.class, Customer.class,
|
||||
Entity1.class, Entity2.class, Entity3.class,
|
||||
Info.class, LineItem.class, Order.class, Phone.class, Product.class,
|
||||
ShelfLife.class, Spouse.class, Thing.class, ThingWithQuantity.class,
|
||||
VersionedEntity.class
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.test.metamodel;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity1")
|
||||
public class Entity1 {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="entity2_id", nullable = false)
|
||||
private Entity2 entity2;
|
||||
|
||||
private String value;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.test.metamodel;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity2")
|
||||
public class Entity2 {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="entity3_id")
|
||||
private Entity3 entity3;
|
||||
|
||||
private String value;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2015, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.test.metamodel;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "entity3")
|
||||
public class Entity3 {
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
private String value;
|
||||
}
|
Loading…
Reference in New Issue