From 1ff9edfb81057535f436a32b3631a3bc0665bbe3 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Wed, 26 Nov 2014 15:35:22 -0800 Subject: [PATCH] HHH-9330 : Test cases for orphanRemoval=true does not work in bidirectional relationships (without cascading) --- .../onetomany/DeleteOneToManyOrphansTest.java | 185 ++++++++++++++++++ .../test/orphan/onetomany/Feature.java | 65 ++++++ .../test/orphan/onetomany/Product.java | 69 +++++++ .../onetomany/DeleteOneToManyOrphansTest.java | 185 ++++++++++++++++++ .../jpa/test/orphan/onetomany/Feature.java | 72 +++++++ .../jpa/test/orphan/onetomany/Product.java | 69 +++++++ 6 files changed, 645 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/DeleteOneToManyOrphansTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Feature.java create mode 100644 hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Product.java create mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/DeleteOneToManyOrphansTest.java create mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Feature.java create mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Product.java diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/DeleteOneToManyOrphansTest.java b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/DeleteOneToManyOrphansTest.java new file mode 100644 index 0000000000..a7bf344376 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/DeleteOneToManyOrphansTest.java @@ -0,0 +1,185 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.orphan.onetomany; + +import java.util.List; + +import org.junit.Test; + +import org.hibernate.Session; +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; + +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badnmer + */ +public class DeleteOneToManyOrphansTest extends BaseCoreFunctionalTestCase { + + private void createData() { + Session s = openSession(); + s.getTransaction().begin(); + + Feature newFeature = new Feature(); + newFeature.setName("Feature 1"); + s.persist( newFeature ); + + Product product = new Product(); + newFeature.setProduct( product ); + product.getFeatures().add( newFeature ); + s.persist( product ); + + s.getTransaction().commit(); + s.clear(); + + } + + private void cleanupData() { + Session session = openSession(); + session.beginTransaction(); + session.createQuery( "delete Feature" ).executeUpdate(); + session.createQuery( "delete Product" ).executeUpdate(); + session.getTransaction().commit(); + session.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testOrphanedWhileManaged() { + createData(); + + Session session = openSession(); + session.beginTransaction(); + List results = session.createQuery( "from Feature" ).list(); + assertEquals( 1, results.size() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + product.getFeatures().clear();; + session.getTransaction().commit(); + session.close(); + + session = openSession(); + session.beginTransaction(); + + product = ( Product ) session.get( Product.class, product.getId() ); + assertEquals( 0, product.getFeatures().size() ); + results = session.createQuery( "from Feature" ).list(); + assertEquals( 0, results.size() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + + session.getTransaction().commit(); + session.close(); + + cleanupData(); + } + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testOrphanedWhileManagedMergeOwner() { + createData(); + + Session session = openSession(); + session.beginTransaction(); + List results = session.createQuery( "from Feature" ).list(); + assertEquals( 1, results.size() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + product.getFeatures().clear(); + session.merge( product ); + session.getTransaction().commit(); + session.close(); + + session = openSession(); + session.beginTransaction(); + + product = ( Product ) session.get( Product.class, product.getId() ); + assertEquals( 0, product.getFeatures().size() ); + results = session.createQuery( "from Feature" ).list(); + assertEquals( 0, results.size() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + + session.getTransaction().commit(); + session.close(); + + cleanupData(); + } + + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testReplacedWhileManaged() { + createData(); + + Session session = openSession(); + session.beginTransaction(); + List results = session.createQuery( "from Feature" ).list(); + assertEquals( 1, results.size() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + + // Replace with a new Feature instance + product.getFeatures().remove( 0 ); + Feature featureNew = new Feature(); + featureNew.setName( "Feature 2" ); + featureNew.setProduct( product ); + product.getFeatures().add( featureNew ); + session.persist( featureNew ); + session.getTransaction().commit(); + session.close(); + + session = openSession(); + session.beginTransaction(); + results = session.createQuery( "from Feature" ).list(); + assertEquals( 1, results.size() ); + Feature featureQueried = (Feature) results.get( 0 ); + assertEquals( featureNew.getId(), featureQueried.getId() ); + results = session.createQuery( "from Product" ).list(); + assertEquals( 1, results.size() ); + Product productQueried = (Product) results.get( 0 ); + assertEquals( 1, productQueried.getFeatures().size() ); + assertEquals( featureQueried, productQueried.getFeatures().get( 0 ) ); + + session.getTransaction().commit(); + session.close(); + + cleanupData(); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + Product.class, + Feature.class + }; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Feature.java b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Feature.java new file mode 100644 index 0000000000..6d535b0b1d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Feature.java @@ -0,0 +1,65 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.orphan.onetomany; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name="feature") +public class Feature { + @Id @GeneratedValue(strategy= GenerationType.AUTO) + private Long id; + + @ManyToOne() + private Product product; + + private String name; + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public Product getProduct() { + return product; + } + public void setProduct(Product product) { + this.product = product; + } +} + diff --git a/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Product.java b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Product.java new file mode 100644 index 0000000000..9dfe27f317 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/orphan/onetomany/Product.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name="product") +public class Product { + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private Long id; + + @OneToMany(mappedBy = "product", orphanRemoval = true) + //, cascade ={CascadeType.PERSIST} + private List features = new ArrayList(); + + private String name; + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public List getFeatures() { + return features; + } + public void setFeatures(List features) { + this.features = features; + } +} + diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/DeleteOneToManyOrphansTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/DeleteOneToManyOrphansTest.java new file mode 100644 index 0000000000..67ad0b8722 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/DeleteOneToManyOrphansTest.java @@ -0,0 +1,185 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.orphan.onetomany; + +import java.util.List; + +import javax.persistence.EntityManager; + +import org.junit.Test; + +import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.testing.TestForIssue; + +import static org.junit.Assert.assertEquals; + +/** + * @author Gail Badner + */ +public class DeleteOneToManyOrphansTest extends BaseEntityManagerFunctionalTestCase { + + private void createData() { + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + + Feature newFeature = new Feature(); + newFeature.setName("Feature 1"); + entityManager.persist( newFeature ); + + Product product = new Product(); + newFeature.setProduct( product ); + product.getFeatures().add( newFeature ); + entityManager.persist( product ); + + entityManager.getTransaction().commit(); + entityManager.clear(); + + } + + private void cleanupData() { + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + entityManager.createQuery( "delete Feature" ).executeUpdate(); + entityManager.createQuery( "delete Product" ).executeUpdate(); + entityManager.getTransaction().commit(); + entityManager.close(); + } + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testOrphanedWhileManaged() { + createData(); + + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + List results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 1, results.size() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + product.getFeatures().clear(); + entityManager.getTransaction().commit(); + entityManager.close(); + + entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + + product = entityManager.find( Product.class, product.getId() ); + assertEquals( 0, product.getFeatures().size() ); + results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 0, results.size() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + + entityManager.getTransaction().commit(); + entityManager.close(); + + cleanupData(); + } + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testOrphanedWhileManagedMergeOwner() { + createData(); + + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + List results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 1, results.size() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + product.getFeatures().clear(); + entityManager.merge( product ); + entityManager.getTransaction().commit(); + entityManager.close(); + + entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + + product = entityManager.find( Product.class, product.getId() ); + assertEquals( 0, product.getFeatures().size() ); + results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 0, results.size() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + + entityManager.getTransaction().commit(); + entityManager.close(); + + cleanupData(); + } + + @Test + @TestForIssue( jiraKey = "HHH-9330") + public void testReplacedWhileManaged() { + createData(); + + EntityManager entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + List results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 1, results.size() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + Product product = ( Product ) results.get( 0 ); + assertEquals( 1, product.getFeatures().size() ); + + // Replace with a new Feature instance + product.getFeatures().remove( 0 ); + Feature featureNew = new Feature(); + featureNew.setName( "Feature 2" ); + featureNew.setProduct( product ); + product.getFeatures().add( featureNew ); + entityManager.persist( featureNew ); + entityManager.getTransaction().commit(); + entityManager.close(); + + entityManager = getOrCreateEntityManager(); + entityManager.getTransaction().begin(); + results = entityManager.createQuery( "from Feature" ).getResultList(); + assertEquals( 1, results.size() ); + Feature featureQueried = (Feature) results.get( 0 ); + assertEquals( featureNew.getId(), featureQueried.getId() ); + results = entityManager.createQuery( "from Product" ).getResultList(); + assertEquals( 1, results.size() ); + Product productQueried = (Product) results.get( 0 ); + assertEquals( 1, productQueried.getFeatures().size() ); + assertEquals( featureQueried, productQueried.getFeatures().get( 0 ) ); + + entityManager.getTransaction().commit(); + entityManager.close(); + + cleanupData(); + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + Product.class, + Feature.class + }; + } +} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Feature.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Feature.java new file mode 100644 index 0000000000..5e87700099 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Feature.java @@ -0,0 +1,72 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.orphan.onetomany; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity +@Table(name="feature") +public class Feature { + @Id @GeneratedValue(strategy= GenerationType.AUTO) + private Long id; + + @ManyToOne() + private Product product; + + private String name; + + public Feature() { + } + + public Feature(Product product) { + this.product = product; + } + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public Product getProduct() { + return product; + } + public void setProduct(Product product) { + this.product = product; + } +} + diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Product.java b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Product.java new file mode 100644 index 0000000000..2e36641cc9 --- /dev/null +++ b/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/orphan/onetomany/Product.java @@ -0,0 +1,69 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2014, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.jpa.test.orphan.onetomany; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name="product") +public class Product { + @Id + @GeneratedValue(strategy= GenerationType.AUTO) + private Long id; + + @OneToMany(mappedBy = "product", orphanRemoval = true) + //, cascade ={CascadeType.PERSIST} + private List features = new ArrayList(); + + private String name; + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public List getFeatures() { + return features; + } + public void setFeatures(List features) { + this.features = features; + } +} +