From b6aa19172057e0d3169dcbc0b5c18c300bd1b067 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Thu, 29 Sep 2016 16:00:33 +0200 Subject: [PATCH] Test and fix for HHH-11140 --- .../hql/internal/ast/tree/FromElement.java | 13 ++++++ .../hql/internal/ast/tree/SelectClause.java | 4 +- .../map/MultilingualStringParent.java | 40 +++++++++++++++++ .../collection/map/PersistentMapTest.java | 45 +++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/collection/map/MultilingualStringParent.java diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java index 2d8c8dffef..d1a82f6630 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElement.java @@ -455,6 +455,19 @@ public class FromElement extends HqlSqlWalkerNode implements DisplayableNode, Pa return origin; } + public FromElement getFetchOrigin() { + if ( origin == null ) { + return null; + } + if ( !origin.isFetch() ) { + return origin; + } + if ( origin.getText() == null || "".equals( origin.getText() ) ) { + return origin.getFetchOrigin(); + } + return origin; + } + public static final String DISCRIMINATOR_PROPERTY_NAME = "class"; private TypeDiscriminatorMetadata typeDiscriminatorMetadata; diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java index 96ba23d6cd..c5038f55e8 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java @@ -207,7 +207,9 @@ public class SelectClause extends SelectExpressionList { else { origin = fromElement.getRealOrigin(); } - if ( !fromElementsForLoad.contains( origin ) ) { + if ( !fromElementsForLoad.contains( origin ) + // work around that fetch joins of element collections where their parent instead of the root is selected + && ( !fromElement.isCollectionJoin() || !fromElementsForLoad.contains( fromElement.getFetchOrigin() ) ) ) { throw new QueryException( "query specified join fetching, but the owner " + "of the fetched association was not present in the select list " + diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/MultilingualStringParent.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/MultilingualStringParent.java new file mode 100644 index 0000000000..aba7618b7d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/MultilingualStringParent.java @@ -0,0 +1,40 @@ +package org.hibernate.test.collection.map; + +import javax.persistence.*; + +@Entity +@Table(name = "multilingual_parent") +public class MultilingualStringParent { + + @Id + @GeneratedValue + private long id; + @ManyToOne(fetch = FetchType.LAZY) + private MultilingualStringParent parent; + @ManyToOne(fetch = FetchType.LAZY) + private MultilingualString string; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public MultilingualStringParent getParent() { + return parent; + } + + public void setParent(MultilingualStringParent parent) { + this.parent = parent; + } + + public MultilingualString getString() { + return string; + } + + public void setString(MultilingualString string) { + this.string = string; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java index 5a3e56bdf2..dbc2e02cf8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/collection/map/PersistentMapTest.java @@ -53,6 +53,7 @@ public class PersistentMapTest extends BaseCoreFunctionalTestCase { User.class, UserData.class, MultilingualString.class, + MultilingualStringParent.class, Address.class, Detail.class }; @@ -238,6 +239,50 @@ public class PersistentMapTest extends BaseCoreFunctionalTestCase { s.close(); } + @Test + @TestForIssue( jiraKey = "HQLPARSER-15") + public void testJoinFetchElementCollectionWithParentSelect() { + Session s = openSession(); + s.getTransaction().begin(); + + MultilingualString m = new MultilingualString(); + LocalizedString localizedString = new LocalizedString(); + localizedString.setLanguage( "English" ); + localizedString.setText( "name" ); + m.getMap().put( localizedString.getLanguage(), localizedString ); + localizedString = new LocalizedString(); + localizedString.setLanguage( "English Pig Latin" ); + localizedString.setText( "amenay" ); + m.getMap().put( localizedString.getLanguage(), localizedString ); + + MultilingualStringParent parent = new MultilingualStringParent(); + parent.setString( m ); + + s.persist( m ); + s.persist( parent ); + s.getTransaction().commit(); + s.close(); + + s = openSession(); + s.beginTransaction(); + m = s.createQuery( + "SELECT s FROM MultilingualStringParent parent " + + "JOIN parent.string s " + + "JOIN FETCH s.map", MultilingualString.class ) + .getSingleResult(); + assertEquals( 2, m.getMap().size() ); + localizedString = m.getMap().get( "English" ); + assertEquals( "English", localizedString.getLanguage() ); + assertEquals( "name", localizedString.getText() ); + localizedString = m.getMap().get( "English Pig Latin" ); + assertEquals( "English Pig Latin", localizedString.getLanguage() ); + assertEquals( "amenay", localizedString.getText() ); + s.delete( parent ); + s.delete( m ); + s.getTransaction().commit(); + s.close(); + } + @Test @TestForIssue( jiraKey = "HHH-11038" ) public void testMapKeyColumnNonInsertableNonUpdatableBidirOneToMany() {