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 dedf9bca1c..8aba25c40b 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 @@ -35,13 +35,13 @@ public class PluralAttributePath extends AbstractPathImpl implements Seria this.persister = resolvePersister( criteriaBuilder, attribute ); } - private static CollectionPersister resolvePersister(CriteriaBuilderImpl criteriaBuilder, PluralAttribute attribute) { + private CollectionPersister resolvePersister(CriteriaBuilderImpl criteriaBuilder, PluralAttribute attribute) { SessionFactoryImplementor sfi = criteriaBuilder.getEntityManagerFactory().getSessionFactory(); return sfi.getCollectionPersister( resolveRole( attribute ) ); } - private static String resolveRole(PluralAttribute attribute) { - return attribute.getDeclaringType().getJavaType().getName() + + private String resolveRole(PluralAttribute attribute) { + return getPathSource().getJavaType().getName() + '.' + attribute.getName(); } diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/BaseEntityManagerFunctionalTestCase.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/BaseEntityManagerFunctionalTestCase.java index 129422cb93..9e92432fde 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/BaseEntityManagerFunctionalTestCase.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/BaseEntityManagerFunctionalTestCase.java @@ -10,6 +10,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -315,6 +316,10 @@ public abstract class BaseEntityManagerFunctionalTestCase extends BaseUnitTestCa return isolatedEm; } + protected EntityManager createEntityManager() { + return createEntityManager( Collections.emptyMap() ); + } + protected EntityManager createEntityManager(Map properties) { // always reopen a new EM and close the existing one if ( em != null && em.isOpen() ) { 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 new file mode 100644 index 0000000000..ed90ed5349 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/criteria/SuperclassCollectionTest.java @@ -0,0 +1,153 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.jpa.test.criteria; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.EntityManager; +import javax.persistence.EntityTransaction; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.MappedSuperclass; +import javax.persistence.OneToMany; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author Janario Oliveira + */ +public class SuperclassCollectionTest extends BaseEntityManagerFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + PersonBase.class, Person.class, Address.class, + OtherSubclass.class + }; + } + + @Test + public void testPerson() { + String address = "super-address"; + String localAddress = "local-address"; + + PersonBase person = createPerson( new Person(), address, localAddress ); + + assertAddress( person, address, localAddress ); + } + + @Test + public void testOtherSubclass() { + String address = "other-super-address"; + String localAddress = "other-local-address"; + PersonBase person = createPerson( new OtherSubclass(), address, localAddress ); + + assertAddress( person, address, localAddress ); + } + + private void assertAddress(PersonBase person, String address, String localAddress) { + List results = find( person.getClass(), person.id, "addresses" ); + assertEquals( 1, results.size() ); + + assertEquals( person.addresses.get( 0 ).id, ( (Address) results.get( 0 ) ).id ); + assertEquals( address, ( (Address) results.get( 0 ) ).name ); + + + results = find( person.getClass(), person.id, "localAddresses" ); + assertEquals( 1, results.size() ); + + assertEquals( person.getLocalAddresses().get( 0 ).id, ( (Address) results.get( 0 ) ).id ); + assertEquals( localAddress, ( (Address) results.get( 0 ) ).name ); + + getOrCreateEntityManager().close(); + } + + private PersonBase createPerson(PersonBase person, String address, String localAddress) { + EntityManager em = createEntityManager(); + EntityTransaction tx = em.getTransaction(); + tx.begin(); + + person.addresses.add( new Address( address ) ); + person.getLocalAddresses().add( new Address( localAddress ) ); + person = em.merge( person ); + tx.commit(); + return person; + } + + private List find(Class clazz, int id, String path) { + EntityManager em = createEntityManager(); + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(); + Root root = cq.from( clazz ); + + cq.select( root.get( path ) ) + .where( cb.equal( root.get( "id" ), id ) ); + + TypedQuery query = em.createQuery( cq ); + return query.getResultList(); + } + + @Entity + public static class Address { + @Id + @GeneratedValue + private Integer id; + private String name; + + protected Address() { + } + + public Address(String name) { + this.name = name; + } + } + + @MappedSuperclass + public abstract static class PersonBase { + @Id + @GeneratedValue + Integer id; + @OneToMany(cascade = CascadeType.ALL) + List
addresses = new ArrayList
(); + + protected abstract List
getLocalAddresses(); + } + + @Entity + public static class Person extends PersonBase { + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "person_localaddress") + List
localAddresses = new ArrayList
(); + + @Override + public List
getLocalAddresses() { + return localAddresses; + } + } + + @Entity + public static class OtherSubclass extends PersonBase { + @OneToMany(cascade = CascadeType.ALL) + @JoinTable(name = "other_person_localaddress") + List
localAddresses = new ArrayList
(); + + @Override + public List
getLocalAddresses() { + return localAddresses; + } + } +}