From 1c2107899aa84bc8c426b99de0c14b6faa2f49d8 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Wed, 9 Mar 2016 16:51:51 -0800 Subject: [PATCH] HHH-10556 : Failure getting a PluralAttributePath for collection declared in a superclass marked @Entity --- .../criteria/path/PluralAttributePath.java | 36 ++++++++++++++++++- .../EntitySuperclassCollectionTest.java | 2 -- .../criteria/SuperclassCollectionTest.java | 28 +++++++++------ 3 files changed, 52 insertions(+), 14 deletions(-) diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/PluralAttributePath.java b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/PluralAttributePath.java index 8aba25c40b..82e3d6dc53 100644 --- a/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/PluralAttributePath.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/jpa/criteria/path/PluralAttributePath.java @@ -9,7 +9,10 @@ package org.hibernate.jpa.criteria.path; import java.io.Serializable; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Bindable; +import javax.persistence.metamodel.EntityType; +import javax.persistence.metamodel.IdentifiableType; import javax.persistence.metamodel.PluralAttribute; +import javax.persistence.metamodel.Type; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.jpa.criteria.CriteriaBuilderImpl; @@ -41,7 +44,38 @@ public class PluralAttributePath extends AbstractPathImpl implements Seria } private String resolveRole(PluralAttribute attribute) { - return getPathSource().getJavaType().getName() + + Class roleOwnerType = attribute.getDeclaringType().getJavaType(); + if ( attribute.getDeclaringType().getPersistenceType() == Type.PersistenceType.MAPPED_SUPERCLASS ) { + // the attribute is declared in a mappedsuperclass + if ( getPathSource().getModel().getBindableType() == Bindable.BindableType.ENTITY_TYPE ) { + // the role will be assigned to the "nearest" EnityType subclass of the MappedSuperclassType + EntityType entityTypeNearestDeclaringType = (EntityType) getPathSource().getModel(); + IdentifiableType superType = entityTypeNearestDeclaringType.getSupertype(); + IdentifiableType previousType = entityTypeNearestDeclaringType; + while ( superType != attribute.getDeclaringType() ) { + if ( superType == null ) { + throw new IllegalStateException( + String.format( + "Cannot determine nearest EntityType extending mapped superclass [%s]; [%s] extends [%s], but supertype of [%s] is null", + attribute.getDeclaringType().getJavaType().getName(), + ( (EntityType) getPathSource().getModel() ).getJavaType().getName(), + previousType.getJavaType().getName(), + previousType.getJavaType().getName() + ) + ); + } + if ( superType.getPersistenceType() == Type.PersistenceType.ENTITY ) { + entityTypeNearestDeclaringType = (EntityType) superType; + } + previousType = superType; + superType = superType.getSupertype(); + } + roleOwnerType = entityTypeNearestDeclaringType.getJavaType(); + } + // else throw an exception? + } + // TODO: still need to deal with a plural attribute declared in an embeddable (HHH-6562) + return roleOwnerType.getName() + '.' + attribute.getName(); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/EntitySuperclassCollectionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/EntitySuperclassCollectionTest.java index 82bdd8e786..ed1cc3e9b7 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/EntitySuperclassCollectionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/EntitySuperclassCollectionTest.java @@ -21,7 +21,6 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; import org.junit.Test; @@ -42,7 +41,6 @@ public class EntitySuperclassCollectionTest extends BaseEntityManagerFunctionalT @Test @TestForIssue( jiraKey = "HHH-10556") - @FailureExpected( jiraKey = "HHH-10556") public void testPerson() { String address = "super-address"; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/SuperclassCollectionTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/SuperclassCollectionTest.java index a27134ff7d..72de902cf0 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/SuperclassCollectionTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/SuperclassCollectionTest.java @@ -23,7 +23,6 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; import org.junit.Test; @@ -38,7 +37,7 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas @Override protected Class[] getAnnotatedClasses() { return new Class[] { - PersonBase.class, Person.class, OtherPerson.class, Address.class, + PersonBaseBase.class, Person.class, OtherPerson.class, Address.class, OtherSubclass.class }; } @@ -48,7 +47,7 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas String address = "super-address"; String localAddress = "local-address"; - PersonBase person = createPerson( new Person(), address, localAddress ); + PersonBaseBase person = createPerson( new Person(), address, localAddress ); assertAddress( person, address, localAddress ); } @@ -57,24 +56,23 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas public void testOtherSubclass() { String address = "other-super-address"; String localAddress = "other-local-address"; - PersonBase person = createPerson( new OtherSubclass(), address, localAddress ); + PersonBaseBase person = createPerson( new OtherSubclass(), address, localAddress ); assertAddress( person, address, localAddress ); } @Test @TestForIssue( jiraKey = "HHH-10556") - @FailureExpected( jiraKey = "HHH-10556") public void testOtherPerson() { String address = "other-person-super-address"; String localAddress = "other-person-local-address"; - PersonBase person = createPerson( new OtherPerson(), address, localAddress ); + PersonBaseBase person = createPerson( new OtherPerson(), address, localAddress ); assertAddress( person, address, localAddress ); } - private void assertAddress(PersonBase person, String address, String localAddress) { + private void assertAddress(PersonBaseBase person, String address, String localAddress) { List results = find( person.getClass(), person.id, "addresses" ); assertEquals( 1, results.size() ); @@ -91,7 +89,7 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas getOrCreateEntityManager().close(); } - private PersonBase createPerson(PersonBase person, String address, String localAddress) { + private PersonBaseBase createPerson(PersonBaseBase person, String address, String localAddress) { EntityManager em = createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); @@ -132,7 +130,7 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas } @MappedSuperclass - public abstract static class PersonBase { + public abstract static class PersonBaseBase { @Id @GeneratedValue Integer id; @@ -142,6 +140,10 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas protected abstract List
getLocalAddresses(); } + @MappedSuperclass + public abstract static class PersonBase extends PersonBaseBase { + } + @Entity(name="Person") public static class Person extends PersonBase { @OneToMany(cascade = CascadeType.ALL) @@ -154,12 +156,16 @@ public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCas } } + @MappedSuperclass + public static class OtherPersonBase extends Person { + } + @Entity(name="OtherPerson") - public static class OtherPerson extends Person { + public static class OtherPerson extends OtherPersonBase { } @Entity(name="OtherSubclass") - public static class OtherSubclass extends PersonBase { + public static class OtherSubclass extends PersonBaseBase { @OneToMany(cascade = CascadeType.ALL) @JoinTable(name = "other_person_localaddress") List
localAddresses = new ArrayList
();