diff --git a/annotations/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java b/annotations/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java index ba268fd736..7bf68ae5d1 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/embedded/many2one/EmbeddableWithMany2OneTest.java @@ -40,7 +40,6 @@ public class EmbeddableWithMany2OneTest extends TestCase { return new Class[] { Person.class, Country.class }; } - @FailureExpected( jiraKey = "HHH-4883") public void testJoinAcrossEmbedded() { Session session = openSession(); session.beginTransaction(); diff --git a/annotations/src/test/java/org/hibernate/test/annotations/embedded/one2many/EmbeddableWithOne2ManyTest.java b/annotations/src/test/java/org/hibernate/test/annotations/embedded/one2many/EmbeddableWithOne2ManyTest.java index e2c9b733ed..0973b9b9be 100644 --- a/annotations/src/test/java/org/hibernate/test/annotations/embedded/one2many/EmbeddableWithOne2ManyTest.java +++ b/annotations/src/test/java/org/hibernate/test/annotations/embedded/one2many/EmbeddableWithOne2ManyTest.java @@ -43,6 +43,8 @@ public class EmbeddableWithOne2ManyTest extends TestCase { @FailureExpected( jiraKey = "HHH-4883") public void testJoinAcrossEmbedded() { + // NOTE : this may or may not work now with HHH-4883 fixed, + // but i cannot do this checking until HHH-4599 is done. Session session = openSession(); session.beginTransaction(); session.createQuery( "from Person p join p.name.aliases a where a.source = 'FBI'" ) diff --git a/core/src/main/java/org/hibernate/hql/ast/tree/DotNode.java b/core/src/main/java/org/hibernate/hql/ast/tree/DotNode.java index 2a55d56ad1..784e1bb234 100644 --- a/core/src/main/java/org/hibernate/hql/ast/tree/DotNode.java +++ b/core/src/main/java/org/hibernate/hql/ast/tree/DotNode.java @@ -445,9 +445,20 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec JoinSequence joinSequence = getSessionFactoryHelper() .createJoinSequence( impliedJoin, propertyType, tableAlias, joinType, joinColumns ); + // 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" ); + } + FromElementFactory factory = new FromElementFactory( currentFromClause, - getLhs().getFromElement(), + lhsFromElement, joinPath, classAlias, joinColumns, diff --git a/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java b/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java index f7fd290835..1dbc5a4c24 100644 --- a/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java +++ b/core/src/main/java/org/hibernate/hql/ast/tree/FromClause.java @@ -275,7 +275,7 @@ public class FromClause extends HqlSqlWalkerNode implements HqlSqlTokenTypes, Di void addJoinByPathMap(String path, FromElement destination) { if ( log.isDebugEnabled() ) { - log.debug( "addJoinByPathMap() : " + path + " -> " + destination ); + log.debug( "addJoinByPathMap() : " + path + " -> " + destination.getDisplayText() ); } fromElementsByPath.put( path, destination ); } diff --git a/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java b/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java index 39792976e5..6d0d171909 100644 --- a/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java +++ b/testsuite/src/test/java/org/hibernate/test/hql/ASTParserLoadingTest.java @@ -83,6 +83,7 @@ public class ASTParserLoadingTest extends FunctionalTestCase { "hql/SimpleEntityWithAssociation.hbm.xml", "hql/CrazyIdFieldNames.hbm.xml", "hql/Image.hbm.xml", + "hql/ComponentContainer.hbm.xml", "batchfetch/ProductLine.hbm.xml", "cid/Customer.hbm.xml", "cid/Order.hbm.xml", @@ -105,6 +106,43 @@ public class ASTParserLoadingTest extends FunctionalTestCase { return new FunctionalTestClassTestSuite( ASTParserLoadingTest.class ); } + public void testComponentJoins() { + Session s = openSession(); + s.beginTransaction(); + ComponentContainer root = new ComponentContainer( + new ComponentContainer.Address( + "123 Main", + "Anywhere", + "USA", + new ComponentContainer.Address.Zip( 12345, 6789 ) + ) + ); + s.save( root ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + List result = s.createQuery( "select a from ComponentContainer c join c.address a" ).list(); + assertEquals( 1, result.size() ); + assertTrue( ComponentContainer.Address.class.isInstance( result.get( 0 ) ) ); + + result = s.createQuery( "select a.zip from ComponentContainer c join c.address a" ).list(); + assertEquals( 1, result.size() ); + assertTrue( ComponentContainer.Address.Zip.class.isInstance( result.get( 0 ) ) ); + + result = s.createQuery( "select z from ComponentContainer c join c.address a join a.zip z" ).list(); + assertEquals( 1, result.size() ); + assertTrue( ComponentContainer.Address.Zip.class.isInstance( result.get( 0 ) ) ); + + result = s.createQuery( "select z.code from ComponentContainer c join c.address a join a.zip z" ).list(); + assertEquals( 1, result.size() ); + assertTrue( Integer.class.isInstance( result.get( 0 ) ) ); + s.delete( root ); + s.getTransaction().commit(); + s.close(); + } + public void testJPAQLQualifiedIdentificationVariables() { Session s = openSession(); s.beginTransaction(); diff --git a/testsuite/src/test/java/org/hibernate/test/hql/ComponentContainer.java b/testsuite/src/test/java/org/hibernate/test/hql/ComponentContainer.java index ab1483c559..2d33bd6bcc 100644 --- a/testsuite/src/test/java/org/hibernate/test/hql/ComponentContainer.java +++ b/testsuite/src/test/java/org/hibernate/test/hql/ComponentContainer.java @@ -10,6 +10,13 @@ public class ComponentContainer { private Long id; private ComponentContainer.Address address; + public ComponentContainer() { + } + + public ComponentContainer(Address address) { + this.address = address; + } + public Long getId() { return id; }