diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java index 8e2f504fb0..fe94f921ad 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/EnhancerTest.java @@ -23,6 +23,8 @@ import org.hibernate.test.bytecode.enhancement.join.HHH3949TestTask1; import org.hibernate.test.bytecode.enhancement.join.HHH3949TestTask2; import org.hibernate.test.bytecode.enhancement.join.HHH3949TestTask3; import org.hibernate.test.bytecode.enhancement.join.HHH3949TestTask4; +import org.hibernate.test.bytecode.enhancement.lazy.HHH_10708.UnexpectedDeleteOneTestTask; +import org.hibernate.test.bytecode.enhancement.lazy.HHH_10708.UnexpectedDeleteTwoTestTask; import org.hibernate.test.bytecode.enhancement.lazy.LazyBasicFieldNotInitializedTestTask; import org.hibernate.test.bytecode.enhancement.lazy.LazyCollectionLoadingTestTask; import org.hibernate.test.bytecode.enhancement.lazy.LazyLoadingIntegrationTestTask; @@ -102,6 +104,13 @@ public class EnhancerTest extends BaseUnitTestCase { EnhancerTestUtils.runEnhancerTestTask( LazyEntityLoadingWithClosedSessionTestTask.class ); } + @Test + @TestForIssue( jiraKey = "HHH-10708" ) + public void testLazyUnexpectedDelete() { + EnhancerTestUtils.runEnhancerTestTask( UnexpectedDeleteOneTestTask.class ); + EnhancerTestUtils.runEnhancerTestTask( UnexpectedDeleteTwoTestTask.class ); + } + @Test public void testMerge() { EnhancerTestUtils.runEnhancerTestTask( CompositeMergeTestTask.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteOneTestTask.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteOneTestTask.java new file mode 100644 index 0000000000..b0c683f100 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteOneTestTask.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.bytecode.enhancement.lazy.HHH_10708; + +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; + +import org.hibernate.Session; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask; + +public class UnexpectedDeleteOneTestTask extends AbstractEnhancerTestTask { + + private int fooId; + + public Class[] getAnnotatedClasses() { + return new Class[] {Foo.class, Bar.class}; + } + + public void prepare() { + Configuration cfg = new Configuration(); + cfg.setProperty( AvailableSettings.SHOW_SQL, Boolean.FALSE.toString() ); + cfg.setProperty( AvailableSettings.USE_SQL_COMMENTS, Boolean.TRUE.toString() ); + super.prepare( cfg ); + + Session s = getFactory().openSession(); + s.beginTransaction(); + + Bar bar1 = new Bar(); + Bar bar2 = new Bar(); + Foo foo = new Foo(); + s.save( bar1 ); + s.save( bar2 ); + s.save( foo ); + bar1.foo = foo; + bar2.foo = foo; + fooId = foo.id; + + s.getTransaction().commit(); + s.clear(); + s.close(); + } + + public void execute() { + Session s = getFactory().openSession(); + s.beginTransaction(); + + Foo foo = s.get( Foo.class, fooId ); + + // accessing the collection results in an exception + foo.bar.size(); + + s.flush(); + s.getTransaction().commit(); + s.close(); + } + + protected void cleanup() { + } + + @Entity static class Bar { + static final String FOO = "foo"; + + @Id @GeneratedValue + int id; + + @ManyToOne @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + Foo foo; + } + + @Entity static class Foo { + + @Id @GeneratedValue + int id; + + @OneToMany(orphanRemoval = true, mappedBy = Bar.FOO, targetEntity = Bar.class) @Cascade(CascadeType.ALL) + Set bar = new HashSet<>(); + } + +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTwoTestTask.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTwoTestTask.java new file mode 100644 index 0000000000..e38623dfc4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/lazy/HHH_10708/UnexpectedDeleteTwoTestTask.java @@ -0,0 +1,102 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.test.bytecode.enhancement.lazy.HHH_10708; + +import java.util.HashSet; +import java.util.Set; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +import org.hibernate.Session; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.test.bytecode.enhancement.AbstractEnhancerTestTask; +import org.junit.Assert; + + +public class UnexpectedDeleteTwoTestTask extends AbstractEnhancerTestTask { + + private Bar myBar; + + public Class[] getAnnotatedClasses() { + return new Class[] {Foo.class, Bar.class}; + } + + public void prepare() { + Configuration cfg = new Configuration(); + cfg.setProperty( AvailableSettings.SHOW_SQL, Boolean.FALSE.toString() ); + cfg.setProperty( AvailableSettings.USE_SQL_COMMENTS, Boolean.TRUE.toString() ); + cfg.setProperty( AvailableSettings.USE_SQL_COMMENTS, Boolean.TRUE.toString() ); + super.prepare( cfg ); + + Session s = getFactory().openSession(); + s.beginTransaction(); + + Bar bar = new Bar(); + Foo foo1 = new Foo(); + Foo foo2 = new Foo(); + s.save( bar ); + s.save( foo1 ); + s.save( foo2 ); + + bar.foos.add( foo1 ); + bar.foos.add( foo2 ); + + s.getTransaction().commit(); + s.clear(); + s.close(); + + myBar = bar; + } + + public void execute() { + Session s = getFactory().openSession(); + s.beginTransaction(); + + s.refresh( myBar ); + Assert.assertFalse( myBar.foos.isEmpty() ); + + // The issue is that currently, for some unknown reason, foos are deleted on flush + + s.flush(); + s.getTransaction().commit(); + s.close(); + + s = getFactory().openSession(); + s.beginTransaction(); + + Bar bar = s.get( Bar.class, myBar.id ); + Assert.assertFalse( bar.foos.isEmpty() ); + + s.flush(); + s.getTransaction().commit(); + s.close(); + } + + protected void cleanup() { + } + + @Entity static class Bar { + + @Id @GeneratedValue + int id; + + @ManyToMany(fetch = FetchType.LAZY, targetEntity = Foo.class) + Set foos = new HashSet<>(); + } + + @Entity static class Foo { + + @Id @GeneratedValue + int id; + } + +} \ No newline at end of file