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 1b0affe72665..77d7dbcb025f 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 @@ -339,12 +339,18 @@ public String[] getIdentityColumns() { throw new IllegalStateException( "No table alias for node " + this ); } - final String propertyName = getIdentifierPropertyName(); - - return toColumns( - table, propertyName, - getWalker().getStatementType() == HqlSqlTokenTypes.SELECT - ); + final String[] propertyNames = getIdentifierPropertyNames(); + List columns = new ArrayList<>(); + for ( int i = 0; i < propertyNames.length; i++ ) { + String[] propertyNameColumns = toColumns( + table, propertyNames[i], + getWalker().getStatementType() == HqlSqlTokenTypes.SELECT + ); + for ( int j = 0; j < propertyNameColumns.length; j++ ) { + columns.add( propertyNameColumns[j] ); + } + } + return columns.toArray( new String[columns.size()] ); } public void setCollectionJoin(boolean collectionJoin) { @@ -525,8 +531,8 @@ public CollectionPropertyReference getCollectionPropertyReference(String propert return elementType.getCollectionPropertyReference( propertyName ); } - public String getIdentifierPropertyName() { - return elementType.getIdentifierPropertyName(); + public String[] getIdentifierPropertyNames() { + return elementType.getIdentifierPropertyNames(); } public void setFetch(boolean fetch) { diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java index 7c815b0e0206..872e6dcb1e8b 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/FromElementType.java @@ -14,17 +14,14 @@ import org.hibernate.MappingException; import org.hibernate.QueryException; import org.hibernate.engine.internal.JoinSequence; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.CollectionProperties; import org.hibernate.hql.internal.CollectionSubqueryFactory; import org.hibernate.hql.internal.NameGenerator; import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes; -import org.hibernate.hql.internal.ast.HqlSqlWalker; -import org.hibernate.hql.internal.ast.util.SessionFactoryHelper; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.internal.log.DeprecationLogger; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.loader.PropertyPath; import org.hibernate.param.ParameterSpecification; import org.hibernate.persister.collection.CollectionPropertyMapping; import org.hibernate.persister.collection.CollectionPropertyNames; @@ -33,6 +30,8 @@ import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.persister.entity.Queryable; +import org.hibernate.tuple.IdentifierProperty; +import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EntityType; import org.hibernate.type.Type; @@ -130,18 +129,22 @@ public Queryable getQueryable() { String renderScalarIdentifierSelect(int i) { checkInitialized(); - final String idPropertyName = getIdentifierPropertyName(); - String[] cols = getPropertyMapping( idPropertyName ).toColumns( getTableAlias(), idPropertyName ); - + final String[] idPropertyName = getIdentifierPropertyNames(); StringBuilder buf = new StringBuilder(); - // For property references generate . as - for ( int j = 0; j < cols.length; j++ ) { - String column = cols[j]; - if ( j > 0 ) { - buf.append( ", " ); + int counter = 0; + for ( int j = 0; j < idPropertyName.length; j++ ) { + String propertyName = idPropertyName[j]; + String[] toColumns = getPropertyMapping( propertyName ).toColumns( getTableAlias(), propertyName ); + for ( int h = 0; h < toColumns.length; h++, counter++ ) { + String column = toColumns[h]; + if ( j + h > 0 ) { + buf.append( ", " ); + } + buf.append( column ).append( " as " ).append( NameGenerator.scalarName( i, counter ) ); } - buf.append( column ).append( " as " ).append( NameGenerator.scalarName( i, j ) ); } + + LOG.debug( "Rendered scalar ID select column(s): " + buf ); return buf.toString(); } @@ -682,13 +685,25 @@ public String[] toColumns(String propertyName) throws QueryException, Unsupporte } } - public String getIdentifierPropertyName() { - if ( getEntityPersister() != null && getEntityPersister().getEntityMetamodel() != null - && getEntityPersister().getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) { - return getEntityPersister().getIdentifierPropertyName(); - } - else { - return EntityPersister.ENTITY_ID; + public String[] getIdentifierPropertyNames() { + if ( getEntityPersister() != null ) { + String identifierPropertyName = getEntityPersister().getIdentifierPropertyName(); + if ( identifierPropertyName != null ) { + return new String[] { identifierPropertyName }; + } + else { + final IdentifierProperty identifierProperty = getEntityPersister().getEntityMetamodel() + .getIdentifierProperty(); + if ( identifierProperty.hasIdentifierMapper() && !identifierProperty.isEmbedded() ) { + return new String[] { PropertyPath.IDENTIFIER_MAPPER_PROPERTY }; + } + else { + if ( EmbeddedComponentType.class.isInstance( identifierProperty.getType() ) ) { + return ( (EmbeddedComponentType) identifierProperty.getType() ).getPropertyNames(); + } + } + } } + return new String[] { EntityPersister.ENTITY_ID }; } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index dd87b91f25c5..34dc8572c93c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -2289,7 +2289,7 @@ protected void initSubclassPropertyAliasesMap(PersistentClass model) throws Mapp new String[] {idColumnNames[i]} ); } -// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyName() ) ) { +// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyNames() ) ) { if ( hasIdentifierProperty() ) { subclassPropertyAliases.put( getIdentifierPropertyName() + "." + idPropertyNames[i], diff --git a/hibernate-core/src/test/java/org/hibernate/test/ecid/CompositeIdAssociationsWithEmbeddedCompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/ecid/CompositeIdAssociationsWithEmbeddedCompositeIdTest.java new file mode 100644 index 000000000000..0fa8d59cbdfb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/ecid/CompositeIdAssociationsWithEmbeddedCompositeIdTest.java @@ -0,0 +1,160 @@ +/* + * 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.test.ecid; + +import java.io.Serializable; +import java.util.Iterator; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinColumns; +import javax.persistence.ManyToOne; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * @author Gail Badner + */ +public class CompositeIdAssociationsWithEmbeddedCompositeIdTest extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { Parent.class, Person.class }; + } + + @Test + @TestForIssue( jiraKey = "HHH-13114") + public void testQueries() { + Parent parent1 = new Parent( "Jane", 0 ); + Parent parent2 = new Parent( "Jim", 1 ); + Person person = doInHibernate( + this::sessionFactory, session -> { + Person p = new Person(); + p.setParent1( parent1 ); + p.setParent2( parent2 ); + p.setBirthOrder( 0 ); + session.persist( parent1 ); + session.persist( parent2 ); + session.persist( p ); + return p; + }); + + doInHibernate( + this::sessionFactory, session -> { + checkResult( session.get( Person.class, person ) ); + }); + + + doInHibernate( + this::sessionFactory, session -> { + checkResult( session.createQuery( "from Person p", Person.class ).getSingleResult() ); + }); + + doInHibernate( + this::sessionFactory, session -> { + Iterator iterator = session.createQuery( "from Person p", Person.class ).iterate(); + assertTrue( iterator.hasNext() ); + Person p = iterator.next(); + checkResult( p ); + assertFalse( iterator.hasNext() ); + }); + } + + private void checkResult(Person p) { + assertEquals( "Jane", p.getParent1().name ); + assertEquals( 0, p.getParent1().index ); + assertEquals( "Jim", p.getParent2().name ); + assertEquals( 1, p.getParent2().index ); + } + + @Entity(name = "Person") + public static class Person implements Serializable { + @Id + @JoinColumns( value = { + @JoinColumn(name = "p1Name"), + @JoinColumn(name = "p1Index") + }) + @ManyToOne + private Parent parent1; + + @Id + @JoinColumns( value = { + @JoinColumn(name = "p2Name"), + @JoinColumn(name = "p2Index") + }) + @ManyToOne + private Parent parent2; + + @Id + private int birthOrder; + + private String name; + + public Person() { + } + + public Person(String name, Parent parent1, Parent parent2) { + this(); + setName( name ); + this.parent1 = parent1; + this.parent2 = parent2; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public Parent getParent1() { + return parent1; + } + public void setParent1(Parent parent1) { + this.parent1 = parent1; + } + + public Parent getParent2() { + return parent2; + } + public void setParent2(Parent parent2) { + this.parent2 = parent2; + } + + public int getBirthOrder() { + return birthOrder; + } + public void setBirthOrder(int birthOrder) { + this.birthOrder = birthOrder; + } + } + + @Entity(name = "Parent") + public static class Parent implements Serializable { + @Id + private String name; + + @Id + private int index; + + public Parent() { + } + + public Parent(String name, int index) { + this.name = name; + this.index = index; + } + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInJoinedSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInJoinedSubclassTest.java new file mode 100644 index 000000000000..87b9b39b9c1b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInJoinedSubclassTest.java @@ -0,0 +1,117 @@ +/* + * 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.test.idprops; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class IdPropertyInJoinedSubclassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Human.class, Genius.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Genius() ); + session.persist( new Genius( 1L ) ); + session.persist( new Genius( 1L ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13114") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( + 2, session.createQuery( "from Genius g where g.id = :id", Genius.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Genius g where g.id is null", Genius.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( g ) from Genius g" ).uniqueResult() ); + + assertEquals( + 2, session.createQuery( "from Human h where h.id = :id", Human.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Human h where h.id is null", Human.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( h ) from Human h" ).uniqueResult() ); + } ); + } + + @Entity(name = "Human") + @Inheritance(strategy = InheritanceType.JOINED) + public static class Human { + + private Long realId; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "realId") + public Long getRealId() { + return realId; + } + + public void setRealId(Long realId) { + this.realId = realId; + } + } + + @Entity(name = "Genius") + public static class Genius extends Human { + private Long id; + + public Genius() { + } + + public Genius(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSingleTableSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSingleTableSubclassTest.java new file mode 100644 index 000000000000..fd7e56ef6ea1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSingleTableSubclassTest.java @@ -0,0 +1,116 @@ +/* + * 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.test.idprops; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class IdPropertyInSingleTableSubclassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Human.class, Genius.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Genius() ); + session.persist( new Genius( 1L ) ); + session.persist( new Genius( 1L ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13114") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( + 2, session.createQuery( "from Genius g where g.id = :id", Genius.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Genius g where g.id is null", Genius.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( g ) from Genius g" ).uniqueResult() ); + + assertEquals( + 2, session.createQuery( "from Human h where h.id = :id", Human.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Human h where h.id is null", Human.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( h ) from Human h" ).uniqueResult() ); + } ); + } + + @Entity(name = "Human") + @Inheritance(strategy = InheritanceType.SINGLE_TABLE) + public static class Human { + private Long realId; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "realId") + public Long getRealId() { + return realId; + } + + public void setRealId(Long realId) { + this.realId = realId; + } + } + + @Entity(name = "Genius") + public static class Genius extends Human { + private Long id; + + public Genius() { + } + + public Genius(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSubclassIdInMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSubclassIdInMappedSuperclassTest.java new file mode 100644 index 000000000000..8cbd837d38c0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInSubclassIdInMappedSuperclassTest.java @@ -0,0 +1,123 @@ +/* + * 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.test.idprops; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.MappedSuperclass; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class IdPropertyInSubclassIdInMappedSuperclassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Human.class, Genius.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Genius() ); + session.persist( new Genius( 1L ) ); + session.persist( new Genius( 1L ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13114") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( + 2, session.createQuery( "from Genius g where g.id = :id", Genius.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Genius g where g.id is null", Genius.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( g ) from Genius g" ).uniqueResult() ); + + assertEquals( + 2, session.createQuery( "from Human h where h.id = :id", Human.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Human h where h.id is null", Human.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( h ) from Human h" ).uniqueResult() ); + + } ); + } + + @MappedSuperclass + public static class Animal { + + private Long realId; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "realId") + public Long getRealId() { + return realId; + } + + public void setRealId(Long realId) { + this.realId = realId; + } + } + + @Entity(name = "Human") + @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) + public static class Human extends Animal { + } + + @Entity(name = "Genius") + public static class Genius extends Human { + private Long id; + + public Genius() { + } + + public Genius(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInTablePerClassSubclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInTablePerClassSubclassTest.java new file mode 100644 index 000000000000..5a0ce3f2071b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/IdPropertyInTablePerClassSubclassTest.java @@ -0,0 +1,116 @@ +/* + * 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.test.idprops; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class IdPropertyInTablePerClassSubclassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Human.class, Genius.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Genius() ); + session.persist( new Genius( 1L ) ); + session.persist( new Genius( 1L ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13114") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( + 2, session.createQuery( "from Genius g where g.id = :id", Genius.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Genius g where g.id is null", Genius.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( g ) from Genius g" ).uniqueResult() ); + + assertEquals( + 2, session.createQuery( "from Human h where h.id = :id", Human.class ) + .setParameter( "id", 1L ) + .list() + .size() + ); + + assertEquals( + 1, session.createQuery( "from Human h where h.id is null", Human.class ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( h ) from Human h" ).uniqueResult() ); + + } ); + } + + @Entity(name = "Human") + @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) + public static class Human { + private Long realId; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "realId") + public Long getRealId() { + return realId; + } + + public void setRealId(Long realId) { + this.realId = realId; + } + } + + @Entity(name = "Genius") + public static class Genius extends Human { + private Long id; + + public Genius() { + } + + public Genius(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInEmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInEmbeddedIdTest.java new file mode 100644 index 000000000000..2452e492144a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInEmbeddedIdTest.java @@ -0,0 +1,136 @@ +/* + * 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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdInEmbeddedIdTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0 ) ); + session.persist( new Person( "John Doe", 1 ) ); + session.persist( new Person( "Jane Doe", 0 ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13084") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + + assertEquals( + 1, session.createQuery( "from Person p where p.id = :id", Person.class ) + .setParameter( "id", new PersonId( "John Doe", 0 ) ) + .list() + .size() + ); + + assertEquals( + 2, session.createQuery( "from Person p where p.id.id = :id", Person.class ) + .setParameter( "id", 0 ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + + } ); + } + + @Entity(name = "Person") + public static class Person implements Serializable { + @EmbeddedId + private PersonId personId; + + public Person(String name, int id) { + this(); + personId = new PersonId( name, id ); + } + + protected Person() { + // this form used by Hibernate + } + + public PersonId getPersonId() { + return personId; + } + } + + @Embeddable + public static class PersonId implements Serializable { + private String name; + private Integer id; + + public PersonId() { + } + + public PersonId(String name, int id) { + setName( name ); + setId( id ); + } + + public String getName() { + return name; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PersonId personId = (PersonId) o; + + if ( id != personId.id ) { + return false; + } + return name.equals( personId.name ); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + id; + return result; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInIdClassTest.java new file mode 100644 index 000000000000..79469e812183 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInIdClassTest.java @@ -0,0 +1,139 @@ +/* + * 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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdInIdClassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0 ) ); + session.persist( new Person( "John Doe", 1 ) ); + session.persist( new Person( "Jane Doe", 0 ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13084") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( 2, session.createQuery( "from Person p where p.id = 0", Person.class ).list().size() ); + + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + + } ); + } + + @Entity(name = "Person") + @IdClass(PersonId.class) + public static class Person implements Serializable { + @Id + private String name; + + @Id + private Integer id; + + public Person(String name, Integer id) { + this(); + setName( name ); + setId( id ); + } + + public String getName() { + return name; + } + + public Integer getId() { + return id; + } + + protected Person() { + // this form used by Hibernate + } + + protected void setName(String name) { + this.name = name; + } + + protected void setId(Integer id) { + this.id = id; + } + } + + public static class PersonId implements Serializable { + private String name; + private Integer id; + + public PersonId() { + } + + public PersonId(String name, int id) { + setName( name ); + setId( id ); + } + + public String getName() { + return name; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public void setId(Integer id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PersonId personId = (PersonId) o; + + if ( id != personId.id ) { + return false; + } + return name.equals( personId.name ); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + id; + return result; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInNonJpaCompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInNonJpaCompositeIdTest.java new file mode 100644 index 000000000000..ea557fbee0cf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdInNonJpaCompositeIdTest.java @@ -0,0 +1,84 @@ +/* + * 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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdInNonJpaCompositeIdTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0 ) ); + session.persist( new Person( "John Doe", 1 ) ); + session.persist( new Person( "Jane Doe", 0 ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13084") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( 2, session.createQuery( "from Person p where p.id = 0", Person.class ).list().size() ); + + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + + } ); + } + + @Entity(name = "Person") + public static class Person implements Serializable { + @Id + private String name; + + @Id + private Integer id; + + public Person(String name, Integer id) { + this(); + setName( name ); + setId( id ); + } + + public String getName() { + return name; + } + + public Integer getId() { + return id; + } + + protected Person() { + // this form used by Hibernate + } + + protected void setName(String name) { + this.name = name; + } + + protected void setId(Integer id) { + this.id = id; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfEmbeddedIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfEmbeddedIdTest.java new file mode 100644 index 000000000000..985f0705256b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfEmbeddedIdTest.java @@ -0,0 +1,137 @@ +/* + * 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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdOutOfEmbeddedIdTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0, 6 ) ); + session.persist( new Person( "John Doe", 1, 6 ) ); + session.persist( new Person( "Jane Doe", 0 ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13084") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( + 2, session.createQuery( "from Person p where p.id = :id", Person.class ) + .setParameter( "id", 6 ) + .list() + .size() + ); + + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + + } ); + } + + @Entity(name = "Person") + public static class Person implements Serializable { + @EmbeddedId + private PersonId personId; + + private Integer id; + + public Person(String name, int index) { + this(); + personId = new PersonId( name, index ); + } + + public Person(String name, int index, Integer id) { + this( name, index ); + this.id = id; + } + + protected Person() { + // this form used by Hibernate + } + + public PersonId getPersonId() { + return personId; + } + } + + @Embeddable + public static class PersonId implements Serializable { + private String name; + @Column(name = "ind") + private int index; + + public PersonId() { + } + + public PersonId(String name, int index) { + setName( name ); + setIndex( index ); + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public void setName(String name) { + this.name = name; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PersonId personId = (PersonId) o; + + if ( index != personId.index ) { + return false; + } + return name.equals( personId.name ); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + index; + return result; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfIdClassTest.java new file mode 100644 index 000000000000..233c6efe9447 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfIdClassTest.java @@ -0,0 +1,157 @@ +/* + * 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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.IdClass; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdOutOfIdClassTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0 ) ); + session.persist( new Person( "John Doe", 1, 1 ) ); + session.persist( new Person( "John Doe", 2, 2 ) ); + } ); + } + + + @Test + @TestForIssue(jiraKey = "HHH-13084") + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( 1, session.createQuery( "from Person p where p.id is null", Person.class ).list().size() ); + assertEquals( 2, session.createQuery( "from Person p where p.id is not null", Person.class ).list().size() ); + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + } ); + } + + @Entity(name = "Person") + @IdClass(PersonId.class) + public static class Person implements Serializable { + @Id + private String name; + + @Id + @Column(name = "ind") + private int index; + + private Integer id; + + public Person(String name, int index) { + this(); + setName( name ); + setIndex( index ); + } + + + public Person(String name, int index, int id) { + this( name, index ); + this.id = id; + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public Integer getId() { + return id; + } + + protected Person() { + // this form used by Hibernate + } + + protected void setName(String name) { + this.name = name; + } + + protected void setIndex(int index) { + this.index = index; + } + + protected void setId(Integer id) { + this.id = id; + } + } + + public static class PersonId implements Serializable { + private String name; + private int index; + + public PersonId() { + } + + public PersonId(String name, int index) { + setName( name ); + setIndex( index ); + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public void setName(String name) { + this.name = name; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PersonId personId = (PersonId) o; + + if ( index != personId.index ) { + return false; + } + return name.equals( personId.name ); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + index; + return result; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfNonJpaCompositeIdTest.java b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfNonJpaCompositeIdTest.java new file mode 100644 index 000000000000..8b8d0d0350dc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/idprops/PropertyNamedIdOutOfNonJpaCompositeIdTest.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.test.idprops; + +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.Before; +import org.junit.Test; + +import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author Gail Badner + */ +public class PropertyNamedIdOutOfNonJpaCompositeIdTest extends BaseCoreFunctionalTestCase { + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { Person.class }; + } + + @Before + public void setUp() { + doInHibernate( this::sessionFactory, session -> { + session.persist( new Person( "John Doe", 0 ) ); + session.persist( new Person( "John Doe", 1, 1 ) ); + session.persist( new Person( "John Doe", 2, 2 ) ); + } ); + } + + @Test + public void testHql() { + doInHibernate( this::sessionFactory, session -> { + assertEquals( 1, session.createQuery( "from Person p where p.id = 1", Person.class ).list().size() ); + + assertEquals( 3L, session.createQuery( "select count( p ) from Person p" ).uniqueResult() ); + } ); + } + + @Entity(name = "Person") + public static class Person implements Serializable { + @Id + private String name; + + @Id + @Column(name = "ind") + private int index; + + private Integer id; + + public Person(String name, int index) { + this(); + setName( name ); + setIndex( index ); + } + + + public Person(String name, int index, int id) { + this( name, index ); + this.id = id; + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public Integer getId() { + return id; + } + + protected Person() { + // this form used by Hibernate + } + + protected void setName(String name) { + this.name = name; + } + + protected void setIndex(int index) { + this.index = index; + } + + protected void setId(Integer id) { + this.id = id; + } + } + + public static class PersonId implements Serializable { + private String name; + private int index; + + public PersonId() { + } + + public PersonId(String name, int index) { + setName( name ); + setIndex( index ); + } + + public String getName() { + return name; + } + + public int getIndex() { + return index; + } + + public void setName(String name) { + this.name = name; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + + PersonId personId = (PersonId) o; + + if ( index != personId.index ) { + return false; + } + return name.equals( personId.name ); + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + index; + return result; + } + } +}