From 3d61b9658c415e5737de88165c4b8d33451b1308 Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Mon, 4 Dec 2023 13:52:22 +0100 Subject: [PATCH] HHH-17413 Add test for issue --- .../CaseStatementWithTypeTest.java | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/discriminator/CaseStatementWithTypeTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/discriminator/CaseStatementWithTypeTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/discriminator/CaseStatementWithTypeTest.java new file mode 100644 index 0000000000..d741db72b1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/discriminator/CaseStatementWithTypeTest.java @@ -0,0 +1,214 @@ +/* + * 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.inheritance.discriminator; + +import java.util.List; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Tuple; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Marco Belladelli + */ +@DomainModel( annotatedClasses = { + CaseStatementWithTypeTest.SingleParent.class, + CaseStatementWithTypeTest.SingleChildA.class, + CaseStatementWithTypeTest.SingleChildB.class, + CaseStatementWithTypeTest.JoinedParent.class, + CaseStatementWithTypeTest.JoinedChildA.class, + CaseStatementWithTypeTest.JoinedChildB.class, + CaseStatementWithTypeTest.UnionParent.class, + CaseStatementWithTypeTest.UnionChildA.class, + CaseStatementWithTypeTest.UnionChildB.class, +} ) +@SessionFactory +@Jira( "https://hibernate.atlassian.net/browse/HHH-17413" ) +public class CaseStatementWithTypeTest { + @BeforeAll + public void setUp(SessionFactoryScope scope) { + scope.inTransaction( session -> { + session.persist( new SingleChildA( 1L ) ); + session.persist( new SingleChildB( 2L ) ); + session.persist( new JoinedChildA( 1L ) ); + session.persist( new JoinedChildB( 2L ) ); + session.persist( new UnionChildA( 1L ) ); + session.persist( new UnionChildB( 2L ) ); + } ); + } + + @AfterAll + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( session -> { + session.createMutationQuery( "delete from SingleParent" ).executeUpdate(); + session.createMutationQuery( "delete from JoinedParent" ).executeUpdate(); + session.createMutationQuery( "delete from UnionParent" ).executeUpdate(); + } ); + } + + @Test + public void testSingleTableInheritance(SessionFactoryScope scope) { + executeQuery( scope, SingleParent.class, SingleChildA.class, SingleChildB.class, false ); + executeQuery( scope, SingleParent.class, SingleChildA.class, SingleChildB.class, true ); + } + + @Test + public void testJoinedInheritance(SessionFactoryScope scope) { + executeQuery( scope, JoinedParent.class, JoinedChildA.class, JoinedChildB.class, false ); + executeQuery( scope, JoinedParent.class, JoinedChildA.class, JoinedChildB.class, true ); + } + + @Test + public void testTablePerClassInheritance(SessionFactoryScope scope) { + executeQuery( scope, UnionParent.class, UnionChildA.class, UnionChildB.class, false ); + executeQuery( scope, UnionParent.class, UnionChildA.class, UnionChildB.class, true ); + } + + private void executeQuery( + SessionFactoryScope scope, + Class parent, + Class childA, + Class childB, + boolean orderBy) { + scope.inTransaction( session -> { + final StringBuilder sb = new StringBuilder( "select p.id" ); + final String caseExpression = String.format( + "case type(p) when %s then 'A' when %s then 'B' else null end", + childA.getSimpleName(), + childB.getSimpleName() + ); + if ( orderBy ) { + sb.append( String.format( " from %s p order by %s", parent.getSimpleName(), caseExpression ) ); + } + else { + sb.append( String.format( ", %s from %s p", caseExpression, parent.getSimpleName() ) ); + } + final List resultList = session.createQuery( sb.toString(), Tuple.class ).getResultList(); + assertThat( resultList ).hasSize( 2 ); + if ( orderBy ) { + assertThat( resultList.stream().map( t -> t.get( 0, Long.class ) ) ).containsExactly( 1L, 2L ); + } + else { + assertThat( resultList.stream().map( t -> t.get( 1, String.class ) ) ).contains( "A", "B" ); + } + } ); + } + + @Entity( name = "SingleParent" ) + @Inheritance( strategy = InheritanceType.SINGLE_TABLE ) + public static class SingleParent { + @Id + private Long id; + + public SingleParent() { + } + + public SingleParent(Long id) { + this.id = id; + } + } + + @Entity( name = "SingleChildA" ) + public static class SingleChildA extends SingleParent { + public SingleChildA() { + } + + public SingleChildA(Long id) { + super( id ); + } + } + + @Entity( name = "SingleChildB" ) + public static class SingleChildB extends SingleParent { + public SingleChildB() { + } + + public SingleChildB(Long id) { + super( id ); + } + } + + @Entity( name = "JoinedParent" ) + @Inheritance( strategy = InheritanceType.JOINED ) + public static class JoinedParent { + @Id + private Long id; + + public JoinedParent() { + } + + public JoinedParent(Long id) { + this.id = id; + } + } + + @Entity( name = "JoinedChildA" ) + public static class JoinedChildA extends JoinedParent { + public JoinedChildA() { + } + + public JoinedChildA(Long id) { + super( id ); + } + } + + @Entity( name = "JoinedChildB" ) + public static class JoinedChildB extends JoinedParent { + public JoinedChildB() { + } + + public JoinedChildB(Long id) { + super( id ); + } + } + + @Entity( name = "UnionParent" ) + @Inheritance( strategy = InheritanceType.TABLE_PER_CLASS ) + public static class UnionParent { + @Id + private Long id; + + public UnionParent() { + } + + public UnionParent(Long id) { + this.id = id; + } + } + + @Entity( name = "UnionChildA" ) + public static class UnionChildA extends UnionParent { + public UnionChildA() { + } + + public UnionChildA(Long id) { + super( id ); + } + } + + @Entity( name = "UnionChildB" ) + public static class UnionChildB extends UnionParent { + public UnionChildB() { + } + + public UnionChildB(Long id) { + super( id ); + } + } +}