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();
|
String propName = getPath();
|
||||||
FromClause currentFromClause = getWalker().getCurrentFromClause();
|
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...
|
// determine whether we should use the table name or table alias to qualify the column names...
|
||||||
// we need to use the table-name when:
|
// we need to use the table-name when:
|
||||||
// 1) the top-level statement is not a SELECT
|
// 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...
|
// the alias also, even if the FromElement is the root one...
|
||||||
//
|
//
|
||||||
// in all other cases, we should use the table alias
|
// in all other cases, we should use the table alias
|
||||||
final FromElement lhsFromElement = getLhs().getFromElement();
|
|
||||||
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT ) {
|
if ( getWalker().getStatementType() != SqlTokenTypes.SELECT ) {
|
||||||
if ( isFromElementUpdateOrDeleteRoot( lhsFromElement ) ) {
|
if ( isFromElementUpdateOrDeleteRoot( lhsFromElement ) ) {
|
||||||
// at this point we know we have the 2 conditions above,
|
// 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
|
// it makes sense to join twice on the same collection role
|
||||||
FromElementFactory factory = new FromElementFactory(
|
FromElementFactory factory = new FromElementFactory(
|
||||||
currentFromClause,
|
currentFromClause,
|
||||||
getLhs().getFromElement(),
|
lhsFromElement,
|
||||||
propName,
|
propName,
|
||||||
classAlias,
|
classAlias,
|
||||||
getColumns(),
|
getColumns(),
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.Query;
|
import org.hibernate.Query;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
|
@ -43,6 +44,7 @@ import org.hibernate.test.util.SchemaUtil;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -407,6 +409,64 @@ public class EmbeddedTest extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
s.close();
|
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
|
@Test
|
||||||
public void testDefaultCollectionTable() throws Exception {
|
public void testDefaultCollectionTable() throws Exception {
|
||||||
//are the tables correct?
|
//are the tables correct?
|
||||||
|
|
|
@ -317,6 +317,75 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
|
||||||
s.close();
|
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
|
@Test
|
||||||
public void testJPAQLQualifiedIdentificationVariablesControl() {
|
public void testJPAQLQualifiedIdentificationVariablesControl() {
|
||||||
// just checking syntax here...
|
// 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;
|
package org.hibernate.jpa.test.criteria.components;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.Query;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.Fetch;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author alan.oleary
|
* @author alan.oleary
|
||||||
*/
|
*/
|
||||||
public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
@Override
|
@Override
|
||||||
public Class[] getAnnotatedClasses() {
|
public Class[] getAnnotatedClasses() {
|
||||||
return new Class[] { Client.class };
|
return new Class[] { Client.class, Alias.class };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -84,6 +91,66 @@ public class ComponentCriteriaTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
em.close();
|
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
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-4586" )
|
@TestForIssue( jiraKey = "HHH-4586" )
|
||||||
public void testParameterizedFunctions() {
|
public void testParameterizedFunctions() {
|
||||||
|
|
|
@ -21,8 +21,13 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.test.criteria.components;
|
package org.hibernate.jpa.test.criteria.components;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name component
|
* The name component
|
||||||
|
@ -35,6 +40,7 @@ public class Name implements Serializable {
|
||||||
|
|
||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
|
private Set<Alias> aliases = new HashSet<Alias>( );
|
||||||
|
|
||||||
public Name() {
|
public Name() {
|
||||||
}
|
}
|
||||||
|
@ -61,4 +67,13 @@ public class Name implements Serializable {
|
||||||
public void setLastName(String lastName) {
|
public void setLastName(String lastName) {
|
||||||
this.lastName = 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