From 9faa764c20ad7a4478f0a77aa67865e53493db4a Mon Sep 17 00:00:00 2001 From: Marco Belladelli Date: Fri, 26 Jan 2024 15:31:44 +0100 Subject: [PATCH] HHH-17679 Add test for issue --- ...ManyToManyJoinTableAndInheritanceTest.java | 199 +++++++++++++++++ ...JoinedInheritanceAndDiscriminatorTest.java | 205 ++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/ManyToManyJoinTableAndInheritanceTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/OneToManyJoinedInheritanceAndDiscriminatorTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/ManyToManyJoinTableAndInheritanceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/ManyToManyJoinTableAndInheritanceTest.java new file mode 100644 index 0000000000..cc91a901d2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/ManyToManyJoinTableAndInheritanceTest.java @@ -0,0 +1,199 @@ +/* + * 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; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.jdbc.SQLStatementInspector; +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.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Marco Belladelli + */ +@DomainModel( annotatedClasses = { + ManyToManyJoinTableAndInheritanceTest.RootEntity.class, + ManyToManyJoinTableAndInheritanceTest.ParentEntity.class, + ManyToManyJoinTableAndInheritanceTest.Sub1.class, +} ) +@SessionFactory( useCollectingStatementInspector = true ) +@Jira( "https://hibernate.atlassian.net/browse/HHH-17679" ) +public class ManyToManyJoinTableAndInheritanceTest { + @BeforeAll + public void setUp(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final Sub1 sub1 = new Sub1( 1L, 1, 1 ); + session.persist( sub1 ); + final RootEntity root = new RootEntity(); + root.getNodesPoly().add( sub1 ); + session.persist( root ); + } ); + } + + @AfterAll + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( session -> { + session.createMutationQuery( "delete from RootEntity" ).executeUpdate(); + session.createMutationQuery( "delete from ParentEntity" ).executeUpdate(); + } ); + } + + @Test + public void testLeftJoinSelectParent(SessionFactoryScope scope) { + final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); + inspector.clear(); + + scope.inTransaction( session -> { + final RootEntity result = session.createQuery( + "select root from RootEntity root left join root.nodesPoly _collection", + RootEntity.class + ).getSingleResult(); + inspector.assertExecutedCount( 1 ); + inspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 ); + assertThat( Hibernate.isInitialized( result.getNodesPoly() ) ).isFalse(); + assertThat( result.getNodesPoly() ).hasSize( 1 ); + assertThat( result.getNodesPoly().iterator().next().getId() ).isEqualTo( 1L ); + } ); + } + + @Test + public void testLeftJoinSelectId(SessionFactoryScope scope) { + final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); + inspector.clear(); + + scope.inTransaction( session -> { + final Long result = session.createQuery( + "select _collection.id from RootEntity root left join root.nodesPoly _collection", + Long.class + ).getSingleResult(); + assertThat( result ).isEqualTo( 1L ); + inspector.assertExecutedCount( 1 ); + inspector.assertNumberOfOccurrenceInQuery( 0, "join", 1 ); + } ); + } + + @Test + public void testLeftJoinSelectElement(SessionFactoryScope scope) { + final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); + inspector.clear(); + + scope.inTransaction( session -> { + final Sub1 result = session.createQuery( + "select _collection from RootEntity root left join root.nodesPoly _collection", + Sub1.class + ).getSingleResult(); + inspector.assertExecutedCount( 1 ); + inspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 ); + assertThat( result.getId() ).isEqualTo( 1L ); + assertThat( result.getNumber() ).isEqualTo( 1 ); + assertThat( result.getSub1Value() ).isEqualTo( 1 ); + } ); + } + + @Test + public void testLeftJoinFetch(SessionFactoryScope scope) { + final SQLStatementInspector inspector = scope.getCollectingStatementInspector(); + inspector.clear(); + + scope.inTransaction( session -> { + final RootEntity result = session.createQuery( + "select root from RootEntity root left join fetch root.nodesPoly _collection", + RootEntity.class + ).getSingleResult(); + inspector.assertExecutedCount( 1 ); + inspector.assertNumberOfOccurrenceInQuery( 0, "join", 2 ); + assertThat( Hibernate.isInitialized( result.getNodesPoly() ) ).isTrue(); + assertThat( result.getNodesPoly() ).hasSize( 1 ); + assertThat( result.getNodesPoly().iterator().next().getId() ).isEqualTo( 1L ); + } ); + } + + @Entity( name = "RootEntity" ) + public static class RootEntity { + @Id + @GeneratedValue + private Long id; + + @ManyToMany + @JoinTable( + name = "set_one_to_many_poly", + joinColumns = @JoinColumn( name = "root_id" ), + inverseJoinColumns = @JoinColumn( name = "poly_id" ) + ) + private Set nodesPoly = new HashSet<>(); + + public Set getNodesPoly() { + return nodesPoly; + } + } + + @Entity( name = "ParentEntity" ) + @DiscriminatorValue( "0" ) + @Inheritance( strategy = InheritanceType.SINGLE_TABLE ) + public static class ParentEntity { + @Id + private Long id; + + @Column( name = "number_col" ) + private Integer number; + + public ParentEntity() { + } + + public ParentEntity(Long id, Integer number) { + this.id = id; + this.number = number; + } + + public Long getId() { + return id; + } + + public Integer getNumber() { + return number; + } + } + + @Entity( name = "Sub1" ) + @DiscriminatorValue( "1" ) + public static class Sub1 extends ParentEntity { + private Integer sub1Value; + + public Sub1() { + } + + public Sub1(Long id, Integer number, Integer sub1Value) { + super( id, number ); + this.sub1Value = sub1Value; + } + + public Integer getSub1Value() { + return sub1Value; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/OneToManyJoinedInheritanceAndDiscriminatorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/OneToManyJoinedInheritanceAndDiscriminatorTest.java new file mode 100644 index 0000000000..e5855eeec4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/OneToManyJoinedInheritanceAndDiscriminatorTest.java @@ -0,0 +1,205 @@ +/* + * 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; + +import java.util.ArrayList; +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.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Marco Belladelli + */ +@SessionFactory +@DomainModel( annotatedClasses = { + OneToManyJoinedInheritanceAndDiscriminatorTest.Company.class, + OneToManyJoinedInheritanceAndDiscriminatorTest.CustomerCompany.class, + OneToManyJoinedInheritanceAndDiscriminatorTest.DistributorCompany.class, + OneToManyJoinedInheritanceAndDiscriminatorTest.ComputerSystem.class, + OneToManyJoinedInheritanceAndDiscriminatorTest.CustomerComputerSystem.class, + OneToManyJoinedInheritanceAndDiscriminatorTest.DistributorComputerSystem.class, +} ) +@Jira( "https://hibernate.atlassian.net/browse/HHH-17483" ) +public class OneToManyJoinedInheritanceAndDiscriminatorTest { + @BeforeAll + public void setUp(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final CustomerComputerSystem customerComputer = new CustomerComputerSystem(); + customerComputer.setId( 1L ); + session.persist( customerComputer ); + final CustomerCompany customerCompany = new CustomerCompany( 2L ); + customerCompany.addComputerSystem( customerComputer ); + session.persist( customerCompany ); + final DistributorComputerSystem distributorComputer = new DistributorComputerSystem(); + distributorComputer.setId( 3L ); + session.persist( distributorComputer ); + final DistributorCompany distributorCompany = new DistributorCompany( 4L ); + distributorCompany.addComputerSystem( distributorComputer ); + session.persist( distributorCompany ); + } ); + } + + @AfterAll + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( session -> { + session.createMutationQuery( "delete from ComputerSystem" ).executeUpdate(); + session.createMutationQuery( "delete from Company" ).executeUpdate(); + } ); + } + + @Test + public void testQuery(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final CustomerCompany result = session.createQuery( + "from CustomerCompany", + CustomerCompany.class + ).getSingleResult(); + assertThat( result.getComputerSystems() ).hasSize( 1 ); + } ); + } + + @Test + public void testFind(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final DistributorCompany result = session.find( DistributorCompany.class, 4L ); + assertThat( result.getComputerSystems() ).hasSize( 1 ); + } ); + } + + @Test + public void testJoinSelectId(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final Long result = session.createQuery( + "select s.id from CustomerCompany c join c.computerSystems s", + Long.class + ).getSingleResult(); + assertThat( result ).isEqualTo( 1L ); + } ); + } + + @Test + public void testJoinSelectEntity(SessionFactoryScope scope) { + scope.inTransaction( session -> { + final DistributorComputerSystem result = session.createQuery( + "select s from DistributorCompany c join c.computerSystems s", + DistributorComputerSystem.class + ).getSingleResult(); + assertThat( result.getId() ).isEqualTo( 3L ); + } ); + } + + @Entity( name = "Company" ) + @Inheritance( strategy = InheritanceType.JOINED ) + public static abstract class Company { + @Id + private Long id; + + public Company() { + } + + public Company(Long id) { + this.id = id; + } + } + + @Entity( name = "CustomerCompany" ) + public static class CustomerCompany extends Company { + @OneToMany( mappedBy = "owner" ) + private List computerSystems = new ArrayList<>(); + + public CustomerCompany() { + } + + public CustomerCompany(long id) { + super( id ); + } + + public void addComputerSystem(CustomerComputerSystem computerSystem) { + computerSystems.add( computerSystem ); + computerSystem.setOwner( this ); + } + + public List getComputerSystems() { + return computerSystems; + } + } + + @Entity( name = "DistributorCompany" ) + public static class DistributorCompany extends Company { + @OneToMany( mappedBy = "owner" ) + private List computerSystems = new ArrayList<>(); + + public DistributorCompany() { + } + + public DistributorCompany(long id) { + super( id ); + } + + public void addComputerSystem(DistributorComputerSystem computerSystem) { + computerSystems.add( computerSystem ); + computerSystem.setOwner( this ); + } + + public List getComputerSystems() { + return computerSystems; + } + } + + @Entity( name = "ComputerSystem" ) + @Table( name = "computer_system" ) + @Inheritance( strategy = InheritanceType.JOINED ) + @DiscriminatorColumn( name = "disc_col" ) + public static abstract class ComputerSystem { + @Id + private Long id; + + @ManyToOne + @JoinColumn( name = "owner_id" ) + private Company owner; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public void setOwner(Company owner) { + this.owner = owner; + } + } + + @Entity( name = "CustomerComputerSystem" ) + @Table( name = "computer_system_sub" ) + public static class CustomerComputerSystem extends ComputerSystem { + } + + @Entity( name = "DistributorComputerSystem" ) + @Table( name = "computer_system_sub" ) + public static class DistributorComputerSystem extends ComputerSystem { + } +}