diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedRoot.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedRoot.java new file mode 100644 index 0000000000..19e4351ca8 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedRoot.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 http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.query.resultmapping; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.EntityResult; +import javax.persistence.FieldResult; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.SqlResultSetMapping; +import javax.persistence.Table; + +/** + * @author Steve Ebersole + */ +@Entity( name = "DiscriminatedRoot" ) +@Table( name = "discriminated_entity" ) +@Inheritance( strategy = InheritanceType.SINGLE_TABLE ) +@DiscriminatorColumn( name = "type_code", length = 20 ) +@DiscriminatorValue( "root" ) +@SqlResultSetMapping( + name = "root-implicit", + entities = @EntityResult( + entityClass = DiscriminatedRoot.class + ) +) +@SqlResultSetMapping( + name = "root-mixed", + entities = @EntityResult( + entityClass = DiscriminatedRoot.class + ) +) +@SqlResultSetMapping( + name = "root-explicit", + entities = @EntityResult( + entityClass = DiscriminatedRoot.class, + discriminatorColumn = "type_code_alias", + fields = { + @FieldResult( name = "id", column = "id_alias" ), + @FieldResult( name = "rootName", column = "root_name_alias" ), + @FieldResult( name = "subType1Name", column = "sub_type1_name_alias" ), + @FieldResult( name = "subType2Name", column = "sub_type2_name_alias" ) + } + ) +) +class DiscriminatedRoot { + private Integer id; + private String rootName; + + public DiscriminatedRoot() { + } + + public DiscriminatedRoot(Integer id, String rootName) { + this.id = id; + this.rootName = rootName; + } + + @Id + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + @Column( name = "root_name" ) + public String getRootName() { + return rootName; + } + + public void setRootName(String rootName) { + this.rootName = rootName; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType1.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType1.java new file mode 100644 index 0000000000..cda82f816a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType1.java @@ -0,0 +1,38 @@ +/* + * 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 http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.query.resultmapping; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +/** + * @author Steve Ebersole + */ +@Entity( name = "DiscriminatedSubType1" ) +@DiscriminatorValue( "subtype1" ) +class DiscriminatedSubType1 extends DiscriminatedRoot { + private String subType1Name; + + public DiscriminatedSubType1() { + super(); + } + + public DiscriminatedSubType1(Integer id, String rootName, String subType1Name) { + super( id, rootName ); + this.subType1Name = subType1Name; + } + + @Column( name = "subtype1_name" ) + public String getSubType1Name() { + return subType1Name; + } + + public void setSubType1Name(String subType1Name) { + this.subType1Name = subType1Name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType2.java new file mode 100644 index 0000000000..4584fb1be2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/DiscriminatedSubType2.java @@ -0,0 +1,38 @@ +/* + * 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 http://www.gnu.org/licenses/lgpl-2.1.html + */ +package org.hibernate.orm.test.query.resultmapping; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +/** + * @author Steve Ebersole + */ +@Entity( name = "DiscriminatedSubType2" ) +@DiscriminatorValue( "subtype2" ) +class DiscriminatedSubType2 extends DiscriminatedRoot { + private String subType2Name; + + public DiscriminatedSubType2() { + super(); + } + + public DiscriminatedSubType2(Integer id, String rootName, String subType2Name) { + super( id, rootName ); + this.subType2Name = subType2Name; + } + + @Column( name = "subtype2_name" ) + public String getSubType2Name() { + return subType2Name; + } + + public void setSubType2Name(String subType2Name) { + this.subType2Name = subType2Name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/EntityResultTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/EntityResultTests.java index 4a21c82a99..a0607bc8c7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/EntityResultTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/resultmapping/EntityResultTests.java @@ -6,13 +6,24 @@ */ package org.hibernate.orm.test.query.resultmapping; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.hibernate.query.named.NamedResultSetMappingMemento; +import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.notNullValue; @@ -20,6 +31,14 @@ import static org.hamcrest.Matchers.notNullValue; /** * @author Steve Ebersole */ +@DomainModel( + annotatedClasses = { + SimpleEntityWithNamedMappings.class, + DiscriminatedRoot.class, + DiscriminatedSubType1.class, + DiscriminatedSubType2.class + } +) public class EntityResultTests extends BaseUsageTest { @Test @@ -107,4 +126,76 @@ public class EntityResultTests extends BaseUsageTest { } ); } + + @Test + public void testExplicitDiscriminatedMapping(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final String qryString = + "select id as id_alias," + + " type_code as type_code_alias," + + " root_name as root_name_alias," + + " subtype1_name as subtype1_name_alias," + + " subtype2_name as subtype2_name_alias" + + " from discriminated_entity"; + + final List results = session.createNativeQuery( qryString, "root-explicit" ).list(); + assertThat( results.size(), is( 4 ) ); + + final Set idsFound = new HashSet<>(); + results.forEach( result -> idsFound.add( result.getId() ) ); + assertThat( idsFound, containsExpectedValues( 1, 2, 3, 4 ) ); + } + ); + } + + public Matcher> containsExpectedValues(T... values) { + return new BaseMatcher>() { + @Override + public void describeTo(Description description) { + description.appendText( "contain expected values" ); + } + + @Override + public boolean matches(Object item) { + if ( ! Collection.class.isInstance( item ) ) { + return false; + } + + //noinspection unchecked + final Collection set = (Collection) item; + final boolean containedAll = set.containsAll( Arrays.asList( values ) ); + + //noinspection RedundantIfStatement + if ( ! containedAll ) { + return false; + } + + return true; + } + }; + } + + @BeforeEach + public void createTestData(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + final DiscriminatedRoot root1 = new DiscriminatedRoot( 1, "root-1" ); + final DiscriminatedRoot root2 = new DiscriminatedRoot( 2, "root-2" ); + final DiscriminatedSubType1 subType1_1 = new DiscriminatedSubType1( 3, "root-3", "sub_type1-1" ); + final DiscriminatedSubType2 subType2_1 = new DiscriminatedSubType2( 4, "root-3", "sub_type2-1" ); + session.persist( root1 ); + session.persist( root2 ); + session.persist( subType1_1 ); + session.persist( subType2_1 ); + } + ); + } + + @AfterEach + public void dropTestData(SessionFactoryScope scope) { + scope.inTransaction( + session -> session.createQuery( "delete DiscriminatedRoot" ).executeUpdate() + ); + } }