HHH-9637 : Join is reused when 2 explicit joins are used for the same ToOne association

(cherry picked from commit 6bb8d03595)

Conflicts:
	hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/metamodel/AbstractMetamodelSpecificTest.java
This commit is contained in:
Gail Badner 2015-06-22 17:56:18 -07:00
parent 55941e6645
commit 74f21115ce
13 changed files with 983 additions and 3 deletions

View File

@ -465,7 +465,7 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
boolean found = elem != null; boolean found = elem != null;
// even though we might find a pre-existing element by join path, we may not be able to reuse it... // 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 ( ! useFoundFromElement ) {
// If this is an implied join in a from element, then use the impled join type which is part of the // If this is an implied join in a from element, then use the impled join type which is part of the
@ -510,9 +510,10 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
setFromElement( elem ); // This 'dot' expression now refers to the resulting from element. 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 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; return true;
} }
@ -520,6 +521,11 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
return getWalker().getCurrentClauseType() != SqlTokenTypes.FROM; 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) { private void setImpliedJoin(FromElement elem) {
this.impliedJoin = elem; this.impliedJoin = elem;
if ( getFirstChild().getType() == SqlTokenTypes.DOT ) { if ( getFirstChild().getType() == SqlTokenTypes.DOT ) {

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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
};
}
}

View File

@ -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
};
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}