diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/MultipleBagsInLazyFetchGroupFtechModeSelectTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/MultipleBagsInLazyFetchGroupFtechModeSelectTest.java new file mode 100644 index 0000000000..420cf86933 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/MultipleBagsInLazyFetchGroupFtechModeSelectTest.java @@ -0,0 +1,114 @@ +/* + * 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.orm.test.bytecode.enhancement.lazy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.boot.SessionFactoryBuilder; +import org.hibernate.engine.spi.SessionImplementor; + +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.runner.RunWith; + +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Christian Beikov + */ +@RunWith(BytecodeEnhancerRunner.class) +public class MultipleBagsInLazyFetchGroupFtechModeSelectTest extends BaseNonConfigCoreFunctionalTestCase { + + @Override + public Class[] getAnnotatedClasses() { + return new Class[] { StringsEntity.class }; + } + + @Override + protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) { + super.configureSessionFactoryBuilder( sfb ); + sfb.applyCollectionsInDefaultFetchGroup( true ); + } + + @After + public void tearDown() { + doInJPA( this::sessionFactory, em -> { + em.createQuery( "delete from StringsEntity" ).executeUpdate(); + } ); + } + + @Before + public void prepare() { + assertTrue( sessionFactory().getSessionFactoryOptions().isCollectionsInDefaultFetchGroupEnabled() ); + + doInJPA( this::sessionFactory, em -> { + StringsEntity entity = new StringsEntity(); + entity.id = 1L; + entity.text = "abc"; + entity.someStrings = new ArrayList<>( Arrays.asList( "a", "b", "c" ) ); + entity.someStrings2 = new ArrayList<>( Arrays.asList( "a", "b", "c", "d" ) ); + em.persist( entity ); + } ); + } + + @Test + public void testGetReference() { + Assertions.assertTrue( sessionFactory().getSessionFactoryOptions().isCollectionsInDefaultFetchGroupEnabled() ); + doInJPA( this::sessionFactory, entityManager -> { + StringsEntity entity = entityManager.getReference( StringsEntity.class, 1L ); + assertEquals( 3, entity.someStrings.size() ); + assertEquals( 4, entity.someStrings2.size() ); + } ); + } + + @Test + public void testFind() { + Assertions.assertTrue( sessionFactory().getSessionFactoryOptions().isCollectionsInDefaultFetchGroupEnabled() ); + doInJPA( this::sessionFactory, entityManager -> { + StringsEntity entity = entityManager.find( StringsEntity.class, 1L ); + assertEquals( 3, entity.someStrings.size() ); + assertEquals( 4, entity.someStrings2.size() ); + + } ); + } + + // --- // + + @Entity(name = "StringsEntity") + @Table(name = "STRINGS_ENTITY") + private static class StringsEntity { + + @Id + Long id; + + String text; + + @ElementCollection(fetch = FetchType.EAGER) + @Fetch(FetchMode.SELECT) + List someStrings; + + @ElementCollection(fetch = FetchType.EAGER) + @Fetch(FetchMode.SELECT) + List someStrings2; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..033c34f457 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoad2Test.java @@ -0,0 +1,260 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class EagerOneToManyPersistAndLoad2Test extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..c0c31f5243 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerOneToManyPersistAndLoadTest.java @@ -0,0 +1,307 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class EagerOneToManyPersistAndLoadTest extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + Parent parent = parents.get( 0 ); + assertThat( parent ).isEqualTo( p ); + + assertThat( parent.getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..c85ebeee1f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoad2Test.java @@ -0,0 +1,263 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class EagerSubSelectOneToManyPersistAndLoad2Test extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @Fetch( FetchMode.SUBSELECT ) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..bc2bc7aedf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/EagerSubSelectOneToManyPersistAndLoadTest.java @@ -0,0 +1,310 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class EagerSubSelectOneToManyPersistAndLoadTest extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + Parent parent = parents.get( 0 ); + assertThat( parent ).isEqualTo( p ); + + assertThat( parent.getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @Fetch( FetchMode.SUBSELECT ) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..08f62f59b2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoad2Test.java @@ -0,0 +1,259 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class LazyOneToManyPersistAndLoad2Test extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertFalse( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertFalse( Hibernate.isInitialized( children ) ); + + assertThat( children.size() ).isEqualTo( 1 ); + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..5ad3375ddf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/LazyOneToManyPersistAndLoadTest.java @@ -0,0 +1,305 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + NoDirtyCheckEnhancementContext.class, // supports laziness; does not support dirty-checking, + DefaultEnhancementContext.class +}) +public class LazyOneToManyPersistAndLoadTest extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + Parent parent = parents.get( 0 ); + assertThat( parent ).isEqualTo( p ); + + assertThat( parent.getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + assertFalse( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + assertFalse( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertFalse( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + assertFalse( Hibernate.isInitialized( p.getChildren() ) ); + + List children = p.getChildren(); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertFalse( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertFalse( Hibernate.isInitialized( children ) ); + + assertThat( children.size() ).isEqualTo( 1 ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/NoDirtyCheckEnhancementContext.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/NoDirtyCheckEnhancementContext.java new file mode 100644 index 0000000000..03356f0fb0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/NoDirtyCheckEnhancementContext.java @@ -0,0 +1,22 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; +import org.hibernate.bytecode.enhance.spi.UnloadedClass; +import org.hibernate.bytecode.enhance.spi.UnloadedField; + +public class NoDirtyCheckEnhancementContext extends DefaultEnhancementContext { + @Override + public boolean hasLazyLoadableAttributes(UnloadedClass classDescriptor) { + return true; + } + + @Override + public boolean isLazyLoadable(UnloadedField field) { + return true; + } + + @Override + public boolean doDirtyCheckingInline(UnloadedClass classDescriptor) { + return false; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..53b1c018cf --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoad2Test.java @@ -0,0 +1,340 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; +import org.hibernate.engine.spi.SessionImplementor; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + DefaultEnhancementContext.class +}) +public class OneToManyPersistAndLoad2Test extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + public static final String CHILD_NAME_2 = "Fab1"; + + public static final String CHILD_NAME_3 = "Fab2"; + public static final String CHILD_NAME_4 = "Fab3"; + public static final String CHILD_NAME_5 = "Fab4"; + + public static final String CHILD_NAME_6 = "Fab5"; + public static final String CHILD_NAME_7 = "Fab6"; + public static final String CHILD_NAME_8 = "Fab7"; + public static final String CHILD_NAME_9 = "Fab8"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1l ); + session.delete( parent ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select distinct p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private Set children; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JoinTable(name = "Parent_child2") + private Set children2; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinTable(name = "Parent_child3") + private Set children3; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public Set getChildren() { + return children; + } + + public Set getChildren2() { + return children2; + } + + public Set getChildren3() { + return children3; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new HashSet<>(); + } + children.add( c ); + } + + public void addChild2(Child c) { + if ( children2 == null ) { + children2 = new HashSet<>(); + } + children2.add( c ); + } + + public void addChild3(Child c) { + if ( children3 == null ) { + children3 = new HashSet<>(); + } + children3.add( c ); + } + + } + + private static void populateParentWithChildren(SessionImplementor session) { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + Child c2 = new Child( CHILD_NAME_2 ); + p.addChild( c2 ); + + Child c3 = new Child( CHILD_NAME_3 ); + p.addChild2( c3 ); + Child c4 = new Child( CHILD_NAME_4 ); + p.addChild2( c4 ); + Child c5 = new Child( CHILD_NAME_5 ); + p.addChild2( c5 ); + + Child c6 = new Child( CHILD_NAME_6 ); + p.addChild3( c6 ); + Child c7 = new Child( CHILD_NAME_7 ); + p.addChild3( c7 ); + Child c8 = new Child( CHILD_NAME_8 ); + p.addChild3( c8 ); + Child c9 = new Child( CHILD_NAME_9 ); + p.addChild3( c9 ); + + session.persist( c ); + session.persist( c2 ); + session.persist( c3 ); + session.persist( c4 ); + session.persist( c5 ); + session.persist( c6 ); + session.persist( c7 ); + session.persist( c8 ); + session.persist( c9 ); + session.persist( p ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..f10661ff83 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/orphan/OneToManyPersistAndLoadTest.java @@ -0,0 +1,340 @@ +package org.hibernate.orm.test.bytecode.enhancement.orphan; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.Hibernate; +import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext; +import org.hibernate.engine.spi.SessionImplementor; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext; +import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@RunWith(BytecodeEnhancerRunner.class) +@CustomEnhancementContext({ + EnhancerTestContext.class, // supports laziness and dirty-checking + DefaultEnhancementContext.class +}) +public class OneToManyPersistAndLoadTest extends BaseCoreFunctionalTestCase { + + public static final String CHILD_NAME = "Luigi"; + public static final String CHILD_NAME_2 = "Fab1"; + + public static final String CHILD_NAME_3 = "Fab2"; + public static final String CHILD_NAME_4 = "Fab3"; + public static final String CHILD_NAME_5 = "Fab4"; + + public static final String CHILD_NAME_6 = "Fab5"; + public static final String CHILD_NAME_7 = "Fab6"; + public static final String CHILD_NAME_8 = "Fab7"; + public static final String CHILD_NAME_9 = "Fab8"; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Parent.class, + Child.class + }; + } + + @After + public void tearDown() { + inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1l ); + session.delete( parent ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery() { + inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch() { + inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select distinct p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Test + public void testCollectionPersistQuery() { + inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private Set children; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JoinTable(name = "Parent_child2") + private Set children2; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinTable(name = "Parent_child3") + private Set children3; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public Set getChildren() { + return children; + } + + public Set getChildren2() { + return children2; + } + + public Set getChildren3() { + return children3; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new HashSet<>(); + } + children.add( c ); + } + + public void addChild2(Child c) { + if ( children2 == null ) { + children2 = new HashSet<>(); + } + children2.add( c ); + } + + public void addChild3(Child c) { + if ( children3 == null ) { + children3 = new HashSet<>(); + } + children3.add( c ); + } + + } + + private static void populateParentWithChildren(SessionImplementor session) { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + Child c2 = new Child( CHILD_NAME_2 ); + p.addChild( c2 ); + + Child c3 = new Child( CHILD_NAME_3 ); + p.addChild2( c3 ); + Child c4 = new Child( CHILD_NAME_4 ); + p.addChild2( c4 ); + Child c5 = new Child( CHILD_NAME_5 ); + p.addChild2( c5 ); + + Child c6 = new Child( CHILD_NAME_6 ); + p.addChild3( c6 ); + Child c7 = new Child( CHILD_NAME_7 ); + p.addChild3( c7 ); + Child c8 = new Child( CHILD_NAME_8 ); + p.addChild3( c8 ); + Child c9 = new Child( CHILD_NAME_9 ); + p.addChild3( c9 ); + + session.persist( c ); + session.persist( c2 ); + session.persist( c3 ); + session.persist( c4 ); + session.persist( c5 ); + session.persist( c6 ); + session.persist( c7 ); + session.persist( c8 ); + session.persist( c9 ); + session.persist( p ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..ec3fb3b946 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoad2Test.java @@ -0,0 +1,250 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + EagerOneToManyPersistAndLoad2Test.Parent.class, + EagerOneToManyPersistAndLoad2Test.Child.class + } +) +@SessionFactory +public class EagerOneToManyPersistAndLoad2Test { + + public static final String CHILD_NAME = "Luigi"; + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..cc5653a9a2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerOneToManyPersistAndLoadTest.java @@ -0,0 +1,295 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + EagerOneToManyPersistAndLoadTest.Parent.class, + EagerOneToManyPersistAndLoadTest.Child.class + } +) +@SessionFactory +public class EagerOneToManyPersistAndLoadTest { + + public static final String CHILD_NAME = "Luigi"; + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..b12102fd7c --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoad2Test.java @@ -0,0 +1,254 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + EagerSubSelectOneToManyPersistAndLoad2Test.Parent.class, + EagerSubSelectOneToManyPersistAndLoad2Test.Child.class + } +) +@SessionFactory +public class EagerSubSelectOneToManyPersistAndLoad2Test { + + public static final String CHILD_NAME = "Luigi"; + + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @Fetch(FetchMode.SUBSELECT) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..9ac08363ab --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/EagerSubSelectOneToManyPersistAndLoadTest.java @@ -0,0 +1,301 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + EagerSubSelectOneToManyPersistAndLoadTest.Parent.class, + EagerSubSelectOneToManyPersistAndLoadTest.Child.class + } +) +@SessionFactory +public class EagerSubSelectOneToManyPersistAndLoadTest { + + public static final String CHILD_NAME = "Luigi"; + + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + Parent parent = parents.get( 0 ); + assertThat( parent ).isEqualTo( p ); + + assertThat( parent.getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertTrue( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @Fetch(FetchMode.SUBSELECT) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..f6b2b6405f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoad2Test.java @@ -0,0 +1,249 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + LazyOneToManyPersistAndLoad2Test.Parent.class, + LazyOneToManyPersistAndLoad2Test.Child.class + } +) +@SessionFactory +public class LazyOneToManyPersistAndLoad2Test { + + public static final String CHILD_NAME = "Luigi"; + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertFalse( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertFalse( Hibernate.isInitialized( children ) ); + + assertThat( children.size() ).isEqualTo( 1 ); + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..9463ca656b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/LazyOneToManyPersistAndLoadTest.java @@ -0,0 +1,292 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Hibernate; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + LazyOneToManyPersistAndLoadTest.Parent.class, + LazyOneToManyPersistAndLoadTest.Child.class + } +) +@SessionFactory +public class LazyOneToManyPersistAndLoadTest { + + public static final String CHILD_NAME = "Luigi"; + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createMutationQuery( "delete from Child" ).executeUpdate(); + session.createMutationQuery( "delete from Parent" ).executeUpdate(); + } + ); + } + + @Test + public void testEmptyCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + List children = p.getChildren(); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( children ).isNull(); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + assertFalse( Hibernate.isInitialized( p.getChildren() ) ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + List children = p.getChildren(); + + assertThat( children ).isEqualTo( parents.get( 0 ).getChildren() ); + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + assertFalse( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertFalse( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistLoad(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + + session.persist( c ); + session.persist( p ); + + List parents = session.createQuery( "from Parent", Parent.class ).getResultList(); + assertThat( parents.size() ).isEqualTo( 1 ); + + List children = parents.get( 0 ).getChildren(); + assertThat( children.size() ).isEqualTo( 1 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + assertFalse( Hibernate.isInitialized( p.getChildren() ) ); + + List children = p.getChildren(); + + List parents = session.createQuery( + "select p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + session.persist( c ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List children = p.getChildren(); + + assertFalse( Hibernate.isInitialized( children ) ); + + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + assertFalse( Hibernate.isInitialized( children ) ); + + assertThat( children.size() ).isEqualTo( 1 ); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + + Child child = children.get( 0 ); + assertThat( child.getName() ).isEqualTo( CHILD_NAME ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + @ManyToOne + private Parent parent; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) + private List children; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public List getChildren() { + return children; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new ArrayList<>(); + } + children.add( c ); + c.setParent( this ); + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoad2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoad2Test.java new file mode 100644 index 0000000000..8ecd9b9ef1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoad2Test.java @@ -0,0 +1,332 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.Hibernate; +import org.hibernate.engine.spi.SessionImplementor; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + OneToManyPersistAndLoad2Test.Parent.class, + OneToManyPersistAndLoad2Test.Child.class + } +) +@SessionFactory +public class OneToManyPersistAndLoad2Test { + + public static final String CHILD_NAME = "Luigi"; + public static final String CHILD_NAME_2 = "Fab1"; + + public static final String CHILD_NAME_3 = "Fab2"; + public static final String CHILD_NAME_4 = "Fab3"; + public static final String CHILD_NAME_5 = "Fab4"; + + public static final String CHILD_NAME_6 = "Fab5"; + public static final String CHILD_NAME_7 = "Fab6"; + public static final String CHILD_NAME_8 = "Fab7"; + public static final String CHILD_NAME_9 = "Fab8"; + + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1l ); + session.delete( parent ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + + List parents = session.createQuery( + "select distinct p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.getReference( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private Set children; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JoinTable(name = "Parent_child2") + private Set children2; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinTable(name = "Parent_child3") + private Set children3; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public Set getChildren() { + return children; + } + + public Set getChildren2() { + return children2; + } + + public Set getChildren3() { + return children3; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new HashSet<>(); + } + children.add( c ); + } + + public void addChild2(Child c) { + if ( children2 == null ) { + children2 = new HashSet<>(); + } + children2.add( c ); + } + + public void addChild3(Child c) { + if ( children3 == null ) { + children3 = new HashSet<>(); + } + children3.add( c ); + } + + } + + private static void populateParentWithChildren(SessionImplementor session) { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + Child c2 = new Child( CHILD_NAME_2 ); + p.addChild( c2 ); + + Child c3 = new Child( CHILD_NAME_3 ); + p.addChild2( c3 ); + Child c4 = new Child( CHILD_NAME_4 ); + p.addChild2( c4 ); + Child c5 = new Child( CHILD_NAME_5 ); + p.addChild2( c5 ); + + Child c6 = new Child( CHILD_NAME_6 ); + p.addChild3( c6 ); + Child c7 = new Child( CHILD_NAME_7 ); + p.addChild3( c7 ); + Child c8 = new Child( CHILD_NAME_8 ); + p.addChild3( c8 ); + Child c9 = new Child( CHILD_NAME_9 ); + p.addChild3( c9 ); + + session.persist( c ); + session.persist( c2 ); + session.persist( c3 ); + session.persist( c4 ); + session.persist( c5 ); + session.persist( c6 ); + session.persist( c7 ); + session.persist( c8 ); + session.persist( c9 ); + session.persist( p ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoadTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoadTest.java new file mode 100644 index 0000000000..af1e9b3865 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/orphan/onetomany/OneToManyPersistAndLoadTest.java @@ -0,0 +1,331 @@ +package org.hibernate.orm.test.jpa.orphan.onetomany; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.hibernate.Hibernate; +import org.hibernate.engine.spi.SessionImplementor; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = "HHH-16334") +@DomainModel( + annotatedClasses = { + OneToManyPersistAndLoadTest.Parent.class, + OneToManyPersistAndLoadTest.Child.class + } +) +@SessionFactory +public class OneToManyPersistAndLoadTest { + + public static final String CHILD_NAME = "Luigi"; + public static final String CHILD_NAME_2 = "Fab1"; + + public static final String CHILD_NAME_3 = "Fab2"; + public static final String CHILD_NAME_4 = "Fab3"; + public static final String CHILD_NAME_5 = "Fab4"; + + public static final String CHILD_NAME_6 = "Fab5"; + public static final String CHILD_NAME_7 = "Fab6"; + public static final String CHILD_NAME_8 = "Fab7"; + public static final String CHILD_NAME_9 = "Fab8"; + + @AfterEach + public void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent parent = session.get( Parent.class, 1l ); + session.delete( parent ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p left join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testEmptyCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Parent p = new Parent( 1l ); + session.persist( p ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select p from Parent p ", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 0 ); + assertThat( children2.size() ).isEqualTo( 0 ); + assertThat( children3.size() ).isEqualTo( 0 ); + } + ); + } + + @Test + public void testCollectionPersistQueryJoinFetch(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + + List parents = session.createQuery( + "select distinct p from Parent p join fetch p.children", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Test + public void testCollectionPersistQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + populateParentWithChildren( session ); + } + ); + + scope.inTransaction( + session -> { + Parent p = session.get( Parent.class, 1l ); + List parents = session.createQuery( + "select p from Parent p", + Parent.class + ).getResultList(); + + assertThat( parents.size() ).isEqualTo( 1 ); + assertThat( parents.get( 0 ) ).isEqualTo( p ); + + Set children = p.getChildren(); + Set children2 = p.getChildren2(); + Set children3 = p.getChildren3(); + + assertThat( parents.get( 0 ).getChildren() ).isEqualTo( children ); + assertThat( parents.get( 0 ).getChildren2() ).isEqualTo( children2 ); + assertThat( parents.get( 0 ).getChildren3() ).isEqualTo( children3 ); + + assertTrue( Hibernate.isInitialized( children ) ); + assertThat( children.size() ).isEqualTo( 2 ); + assertThat( children2.size() ).isEqualTo( 3 ); + assertThat( children3.size() ).isEqualTo( 4 ); + } + ); + } + + @Entity(name = "Child") + public static class Child { + + @Id + @GeneratedValue + private Long id; + + private String name; + + public Child() { + } + + public Child(String name) { + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + } + + @Entity(name = "Parent") + public static class Parent { + + @Id + private Long id; + + private String name; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + private Set children; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER) + @JoinTable(name = "Parent_child2") + private Set children2; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinTable(name = "Parent_child3") + private Set children3; + + public Parent() { + } + + public Parent(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public Set getChildren() { + return children; + } + + public Set getChildren2() { + return children2; + } + + public Set getChildren3() { + return children3; + } + + public void addChild(Child c) { + if ( children == null ) { + children = new HashSet<>(); + } + children.add( c ); + } + + public void addChild2(Child c) { + if ( children2 == null ) { + children2 = new HashSet<>(); + } + children2.add( c ); + } + + public void addChild3(Child c) { + if ( children3 == null ) { + children3 = new HashSet<>(); + } + children3.add( c ); + } + + } + + private static void populateParentWithChildren(SessionImplementor session) { + Parent p = new Parent( 1l ); + Child c = new Child( CHILD_NAME ); + p.addChild( c ); + Child c2 = new Child( CHILD_NAME_2 ); + p.addChild( c2 ); + + Child c3 = new Child( CHILD_NAME_3 ); + p.addChild2( c3 ); + Child c4 = new Child( CHILD_NAME_4 ); + p.addChild2( c4 ); + Child c5 = new Child( CHILD_NAME_5 ); + p.addChild2( c5 ); + + Child c6 = new Child( CHILD_NAME_6 ); + p.addChild3( c6 ); + Child c7 = new Child( CHILD_NAME_7 ); + p.addChild3( c7 ); + Child c8 = new Child( CHILD_NAME_8 ); + p.addChild3( c8 ); + Child c9 = new Child( CHILD_NAME_9 ); + p.addChild3( c9 ); + + session.persist( c ); + session.persist( c2 ); + session.persist( c3 ); + session.persist( c4 ); + session.persist( c5 ); + session.persist( c6 ); + session.persist( c7 ); + session.persist( c8 ); + session.persist( c9 ); + session.persist( p ); + } + +}