HHH-9642 : Join fetch not performing join fetch for @Embeddable with @OneToMany
This commit is contained in:
parent
24bafba2b0
commit
6c404c30f7
|
@ -298,6 +298,17 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
String propName = getPath();
|
||||
FromClause currentFromClause = getWalker().getCurrentFromClause();
|
||||
|
||||
// If the lhs of the join is a "component join", we need to go back to the
|
||||
// first non-component-join as the origin to properly link aliases and
|
||||
// join columns
|
||||
FromElement lhsFromElement = getLhs().getFromElement();
|
||||
while ( lhsFromElement != null && ComponentJoin.class.isInstance( lhsFromElement ) ) {
|
||||
lhsFromElement = lhsFromElement.getOrigin();
|
||||
}
|
||||
if ( lhsFromElement == null ) {
|
||||
throw new QueryException( "Unable to locate appropriate lhs" );
|
||||
}
|
||||
|
||||
// determine whether we should use the table name or table alias to qualify the column names...
|
||||
// we need to use the table-name when:
|
||||
// 1) the top-level statement is not a SELECT
|
||||
|
@ -307,7 +318,6 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
// the alias also, even if the FromElement is the root one...
|
||||
//
|
||||
// in all other cases, we should use the table alias
|
||||
final FromElement lhsFromElement = getLhs().getFromElement();
|
||||
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT ) {
|
||||
if ( isFromElementUpdateOrDeleteRoot( lhsFromElement ) ) {
|
||||
// at this point we know we have the 2 conditions above,
|
||||
|
@ -330,7 +340,7 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
// it makes sense to join twice on the same collection role
|
||||
FromElementFactory factory = new FromElementFactory(
|
||||
currentFromClause,
|
||||
getLhs().getFromElement(),
|
||||
lhsFromElement,
|
||||
propName,
|
||||
classAlias,
|
||||
getColumns(),
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
|
@ -43,6 +44,7 @@ import org.hibernate.test.util.SchemaUtil;
|
|||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
@ -407,6 +409,64 @@ public class EmbeddedTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9642")
|
||||
public void testEmbeddedAndOneToManyHql() throws Exception {
|
||||
Session s;
|
||||
s = openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
InternetProvider provider = new InternetProvider();
|
||||
provider.setBrandName( "Fido" );
|
||||
LegalStructure structure = new LegalStructure();
|
||||
structure.setCountry( "Canada" );
|
||||
structure.setName( "Rogers" );
|
||||
provider.setOwner( structure );
|
||||
s.persist( provider );
|
||||
Manager manager = new Manager();
|
||||
manager.setName( "Bill" );
|
||||
manager.setEmployer( provider );
|
||||
structure.getTopManagement().add( manager );
|
||||
s.persist( manager );
|
||||
tx.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
InternetProvider internetProviderQueried =
|
||||
(InternetProvider) s.createQuery( "from InternetProvider" ).uniqueResult();
|
||||
assertFalse( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
internetProviderQueried =
|
||||
(InternetProvider) s.createQuery( "from InternetProvider i join fetch i.owner.topManagement" )
|
||||
.uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.getTransaction().begin();
|
||||
internetProviderQueried =
|
||||
(InternetProvider) s.createQuery( "from InternetProvider i join fetch i.owner o join fetch o.topManagement" )
|
||||
.uniqueResult();
|
||||
assertTrue( Hibernate.isInitialized( internetProviderQueried.getOwner().getTopManagement() ) );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
tx = s.beginTransaction();
|
||||
provider = (InternetProvider) s.get( InternetProvider.class, provider.getId() );
|
||||
manager = provider.getOwner().getTopManagement().iterator().next();
|
||||
s.delete( manager );
|
||||
s.delete( provider );
|
||||
tx.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDefaultCollectionTable() throws Exception {
|
||||
//are the tables correct?
|
||||
|
|
|
@ -317,6 +317,75 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9642")
|
||||
public void testLazyAssociationInComponent() {
|
||||
Session session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
Address address = new Address();
|
||||
Zoo zoo = new Zoo( "ZOO 1", address );
|
||||
address.setCity( "City 1" );
|
||||
StateProvince stateProvince = new StateProvince();
|
||||
stateProvince.setName( "Illinois" );
|
||||
session.save( stateProvince );
|
||||
address.setStateProvince( stateProvince );
|
||||
session.save( zoo );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
zoo = (Zoo) session.createQuery( "from Zoo z" ).uniqueResult();
|
||||
assertNotNull( zoo );
|
||||
assertNotNull( zoo.getAddress() );
|
||||
assertEquals( "City 1", zoo.getAddress().getCity() );
|
||||
assertFalse( Hibernate.isInitialized( zoo.getAddress().getStateProvince() ) );
|
||||
assertEquals( "Illinois", zoo.getAddress().getStateProvince().getName() );
|
||||
assertTrue( Hibernate.isInitialized( zoo.getAddress().getStateProvince() ) );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
zoo = (Zoo) session.createQuery( "from Zoo z join fetch z.address.stateProvince" ).uniqueResult();
|
||||
assertNotNull( zoo );
|
||||
assertNotNull( zoo.getAddress() );
|
||||
assertEquals( "City 1", zoo.getAddress().getCity() );
|
||||
assertTrue( Hibernate.isInitialized( zoo.getAddress().getStateProvince() ) );
|
||||
assertEquals( "Illinois", zoo.getAddress().getStateProvince().getName() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
zoo = (Zoo) session.createQuery( "from Zoo z join fetch z.address a join fetch a.stateProvince" ).uniqueResult();
|
||||
assertNotNull( zoo );
|
||||
assertNotNull( zoo.getAddress() );
|
||||
assertEquals( "City 1", zoo.getAddress().getCity() );
|
||||
assertTrue( Hibernate.isInitialized( zoo.getAddress().getStateProvince() ) );
|
||||
assertEquals( "Illinois", zoo.getAddress().getStateProvince().getName() );
|
||||
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.getTransaction().begin();
|
||||
|
||||
zoo.getAddress().setStateProvince( null );
|
||||
session.delete( stateProvince );
|
||||
session.delete( zoo );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJPAQLQualifiedIdentificationVariablesControl() {
|
||||
// just checking syntax here...
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, 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.components;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* TODO : javadoc
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Entity
|
||||
public class Alias {
|
||||
private Long id;
|
||||
private Name name;
|
||||
private String source;
|
||||
|
||||
public Alias() {
|
||||
}
|
||||
|
||||
public Alias(String firstName, String lastName, String source) {
|
||||
this( new Name( firstName, lastName ), source );
|
||||
}
|
||||
|
||||
public Alias(Name name, String source) {
|
||||
this.name = name;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Id @GeneratedValue
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Name getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(Name name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
}
|
|
@ -24,26 +24,33 @@
|
|||
package org.hibernate.jpa.test.criteria.components;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Fetch;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author alan.oleary
|
||||
*/
|
||||
public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
||||
@Override
|
||||
public Class[] getAnnotatedClasses() {
|
||||
return new Class[] { Client.class };
|
||||
return new Class[] { Client.class, Alias.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -84,6 +91,66 @@ public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
|||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-9642")
|
||||
public void testOneToManyJoinFetchedInEmbeddable() {
|
||||
EntityManager em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
Client client = new Client( 111, "steve", "ebersole" );
|
||||
Alias alias = new Alias( "a", "guy", "work" );
|
||||
client.getName().getAliases().add( alias );
|
||||
em.persist(client);
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Client> cq = cb.createQuery(Client.class);
|
||||
Root<Client> root = cq.from(Client.class);
|
||||
root.fetch( Client_.name ).fetch( Name_.aliases );
|
||||
cq.where(cb.equal(root.get("name").get("firstName"), client.getName().getFirstName()));
|
||||
List<Client> list = em.createQuery(cq).getResultList();
|
||||
Assert.assertEquals( 1, list.size() );
|
||||
client = list.get( 0 );
|
||||
assertTrue( Hibernate.isInitialized( client.getName().getAliases() ) );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
TypedQuery< Client > q = em.createQuery(
|
||||
"SELECT c FROM Client c JOIN FETCH c.name.aliases WHERE c.name.firstName = '"
|
||||
+ client.getName().getFirstName() + "'",
|
||||
Client.class
|
||||
);
|
||||
Assert.assertEquals( 1, q.getResultList().size() );
|
||||
client = list.get( 0 );
|
||||
assertTrue( Hibernate.isInitialized( client.getName().getAliases() ) );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
q = em.createQuery(
|
||||
"SELECT c FROM Client c JOIN c.name n join FETCH n.aliases WHERE c.name.firstName = '"
|
||||
+ client.getName().getFirstName() + "'",
|
||||
Client.class
|
||||
);
|
||||
Assert.assertEquals( 1, q.getResultList().size() );
|
||||
client = list.get( 0 );
|
||||
assertTrue( Hibernate.isInitialized( client.getName().getAliases() ) );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
|
||||
em = getOrCreateEntityManager();
|
||||
em.getTransaction().begin();
|
||||
client = em.merge( client );
|
||||
em.remove( client );
|
||||
em.getTransaction().commit();
|
||||
em.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-4586" )
|
||||
public void testParameterizedFunctions() {
|
||||
|
|
|
@ -21,8 +21,13 @@
|
|||
*/
|
||||
package org.hibernate.jpa.test.criteria.components;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
/**
|
||||
* The name component
|
||||
|
@ -35,6 +40,7 @@ public class Name implements Serializable {
|
|||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private Set<Alias> aliases = new HashSet<Alias>( );
|
||||
|
||||
public Name() {
|
||||
}
|
||||
|
@ -61,4 +67,13 @@ public class Name implements Serializable {
|
|||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
public Set<Alias> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
public void setAliases(Set<Alias> aliases) {
|
||||
this.aliases = aliases;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue