From 0e43f71ca0ff68bba655a89057508c0619308568 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Mon, 14 Jul 2014 15:28:32 -0700 Subject: [PATCH] HHH-9261 : Backport HHH-9106 to 4.2 (Multiple representations of the same entity cannot be merged using cascade=merge) --- .../internal/DefaultMergeEventListener.java | 79 +++++-- ...B3EntityCopyAllowedMergeEventListener.java | 45 ---- ...MultipleEntityCopiesAllowedLoggedTest.java | 2 +- .../MergeMultipleEntityCopiesAllowedTest.java | 4 +- .../MergeMultipleEntityCopiesCustomTest.java | 4 +- ...leEntityCopiesDisallowedByDefaultTest.java | 4 +- ...rgeMultipleEntityCopiesDisallowedTest.java | 2 +- ...tipleEntityRepresentationsAllowedTest.java | 199 ------------------ ...leEntityRepresentationsNotAllowedTest.java | 175 --------------- 9 files changed, 66 insertions(+), 448 deletions(-) delete mode 100644 hibernate-entitymanager/src/main/java/org/hibernate/ejb/event/EJB3EntityCopyAllowedMergeEventListener.java rename hibernate-entitymanager/src/test/java/org/hibernate/{jpa => ejb}/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java (97%) rename hibernate-entitymanager/src/test/java/org/hibernate/{jpa => ejb}/test/emops/MergeMultipleEntityCopiesAllowedTest.java (98%) rename hibernate-entitymanager/src/test/java/org/hibernate/{jpa => ejb}/test/emops/MergeMultipleEntityCopiesCustomTest.java (98%) rename hibernate-entitymanager/src/test/java/org/hibernate/{jpa => ejb}/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java (97%) rename hibernate-entitymanager/src/test/java/org/hibernate/{jpa => ejb}/test/emops/MergeMultipleEntityCopiesDisallowedTest.java (97%) delete mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsAllowedTest.java delete mode 100644 hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsNotAllowedTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index cedea77ee6..5a2ac4fd58 100755 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -33,9 +33,7 @@ import org.hibernate.HibernateException; import org.hibernate.ObjectDeletedException; import org.hibernate.StaleObjectStateException; import org.hibernate.WrongClassException; -import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.bytecode.instrumentation.spi.FieldInterceptor; -import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.spi.CascadingAction; import org.hibernate.engine.spi.EntityEntry; @@ -51,6 +49,9 @@ import org.hibernate.persister.entity.EntityPersister; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.hibernate.service.ServiceRegistry; +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.classloading.spi.ClassLoadingException; +import org.hibernate.service.config.spi.ConfigurationService; import org.hibernate.type.ForeignKeyDirection; import org.hibernate.type.TypeHelper; @@ -64,8 +65,8 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, DefaultMergeEventListener.class.getName()); - - private String entityCopyObserverStrategy; + private static final String ENTITY_COPY_OBSERVER_STRATEGY_PROPERTY_NAME = "hibernate.event.merge.entity_copy_observer"; + private Class entityCopyObserverClass; @Override protected Map getMergeMap(Object anything) { @@ -92,24 +93,18 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme } private EntityCopyObserver createEntityCopyObserver(SessionFactoryImplementor sessionFactory) { - final ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry(); - if ( entityCopyObserverStrategy == null ) { - final ConfigurationService configurationService - = serviceRegistry.getService( ConfigurationService.class ); - entityCopyObserverStrategy = configurationService.getSetting( - "hibernate.event.merge.entity_copy_observer", - new ConfigurationService.Converter() { - @Override - public String convert(Object value) { - return value.toString(); - } - }, - EntityCopyNotAllowedObserver.SHORT_NAME - ); - LOG.debugf( "EntityCopyObserver strategy: %s", entityCopyObserverStrategy ); + if ( entityCopyObserverClass == null ) { + entityCopyObserverClass = determineEntityCopyObserverClass( sessionFactory ); + } + try { + return entityCopyObserverClass.newInstance(); + } + catch (Exception e) { + throw new HibernateException( + String.format( "Could not instantiate EntityCopyObserver implementation [%s]", entityCopyObserverClass.getName() ), + e + ); } - final StrategySelector strategySelector = serviceRegistry.getService( StrategySelector.class ); - return strategySelector.resolveStrategy( EntityCopyObserver.class, entityCopyObserverStrategy ); } /** @@ -504,4 +499,46 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme protected void cascadeBeforeSave(EventSource source, EntityPersister persister, Object entity, Object anything) throws HibernateException { } + + private static Class determineEntityCopyObserverClass( + SessionFactoryImplementor sessionFactory) { + final ServiceRegistry serviceRegistry = sessionFactory.getServiceRegistry(); + final ConfigurationService configurationService + = serviceRegistry.getService( ConfigurationService.class ); + final String entityCopyObserverStrategyString = configurationService.getSetting( + ENTITY_COPY_OBSERVER_STRATEGY_PROPERTY_NAME, + new ConfigurationService.Converter() { + @Override + public String convert(Object value) { + return value.toString(); + } + }, + EntityCopyNotAllowedObserver.SHORT_NAME + ); + LOG.debugf( "EntityCopyObserver strategy: %s", entityCopyObserverStrategyString ); + if ( EntityCopyNotAllowedObserver.SHORT_NAME.equals( entityCopyObserverStrategyString ) ) { + return EntityCopyNotAllowedObserver.class; + } + else if ( EntityCopyAllowedObserver.SHORT_NAME.equals( entityCopyObserverStrategyString ) ) { + return EntityCopyAllowedObserver.class; + } + else if ( EntityCopyAllowedLoggedObserver.SHORT_NAME.equals( entityCopyObserverStrategyString ) ) { + return EntityCopyAllowedLoggedObserver.class; + } + else { + final ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class ); + try { + return classLoaderService.classForName( entityCopyObserverStrategyString ); + } + catch (ClassLoadingException e) { + throw new HibernateException( + "Unable resolve strategy [" + + entityCopyObserverStrategyString + + "] as strategy for [" + + ENTITY_COPY_OBSERVER_STRATEGY_PROPERTY_NAME + "]", + e + ); + } + } + } } diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/event/EJB3EntityCopyAllowedMergeEventListener.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/event/EJB3EntityCopyAllowedMergeEventListener.java deleted file mode 100644 index 72ddc20bf9..0000000000 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/event/EJB3EntityCopyAllowedMergeEventListener.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.ejb.event; - -import org.hibernate.event.internal.EntityCopyAllowedLoggedObserver; -import org.hibernate.event.internal.EntityCopyAllowedObserver; -import org.hibernate.event.internal.EntityCopyObserver; - -/** - * Overrides {@link EJB3MergeEventListener} that allows merging multiple representations - * of the same persistent entity. - * - * @author Gail Badner - */ -public class EJB3EntityCopyAllowedMergeEventListener extends EJB3MergeEventListener { - - @Override - protected EntityCopyObserver createEntityCopyObserver() { - return EntityCopyAllowedLoggedObserver.isDebugLoggingEnabled() ? - new EntityCopyAllowedLoggedObserver() : - new EntityCopyAllowedObserver(); - } - -} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java similarity index 97% rename from hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java rename to hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java index 9962d79614..7531bf3a9f 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedLoggedTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.jpa.test.emops; +package org.hibernate.ejb.test.emops; import java.util.Map; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedTest.java similarity index 98% rename from hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedTest.java rename to hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedTest.java index fa1f86df83..873b039fd5 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesAllowedTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesAllowedTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.jpa.test.emops; +package org.hibernate.ejb.test.emops; import java.util.List; import java.util.Map; @@ -29,7 +29,7 @@ import javax.persistence.EntityManager; import org.junit.Test; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import static org.junit.Assert.assertFalse; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesCustomTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesCustomTest.java similarity index 98% rename from hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesCustomTest.java rename to hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesCustomTest.java index e690bd7e6f..41627083eb 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesCustomTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesCustomTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.jpa.test.emops; +package org.hibernate.ejb.test.emops; import java.util.List; import java.util.Map; @@ -33,7 +33,7 @@ import org.junit.Test; import org.hibernate.Hibernate; import org.hibernate.event.spi.EntityCopyObserver; import org.hibernate.event.spi.EventSource; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import static junit.framework.TestCase.fail; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java similarity index 97% rename from hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java rename to hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java index 3f06e482dd..324ac977b3 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedByDefaultTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.jpa.test.emops; +package org.hibernate.ejb.test.emops; import java.util.List; @@ -29,7 +29,7 @@ import javax.persistence.EntityManager; import org.junit.Test; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.testing.TestForIssue; import static junit.framework.TestCase.fail; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedTest.java similarity index 97% rename from hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedTest.java rename to hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedTest.java index fbab7cef86..423f84e910 100644 --- a/hibernate-entitymanager/src/test/java/org/hibernate/jpa/test/emops/MergeMultipleEntityCopiesDisallowedTest.java +++ b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityCopiesDisallowedTest.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.jpa.test.emops; +package org.hibernate.ejb.test.emops; import java.util.Map; diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsAllowedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsAllowedTest.java deleted file mode 100644 index 2388cad9b5..0000000000 --- a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsAllowedTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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.ejb.test.emops; - -import java.util.List; -import javax.persistence.EntityManager; - -import org.junit.Test; - -import org.hibernate.SessionFactory; -import org.hibernate.ejb.HibernateEntityManagerFactory; -import org.hibernate.ejb.event.EJB3EntityCopyAllowedMergeEventListener; -import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.event.service.spi.EventListenerRegistry; -import org.hibernate.event.spi.EventType; -import org.hibernate.testing.TestForIssue; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - -/** - * Tests merging multiple detached representations of the same entity using - * {@link org.hibernate.ejb.event.EJB3EntityCopyAllowedMergeEventListener}. - * - * @author Gail Badner - */ -@TestForIssue( jiraKey = "HHH-9106") -public class MergeMultipleEntityRepresentationsAllowedTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected void afterEntityManagerFactoryBuilt() { - super.afterEntityManagerFactoryBuilt(); - SessionFactory sf = ( (HibernateEntityManagerFactory) entityManagerFactory() ).getSessionFactory(); - EventListenerRegistry registry = - ( (SessionFactoryImplementor) sf ).getServiceRegistry().getService( EventListenerRegistry.class ); - registry.setListeners( EventType.MERGE, new EJB3EntityCopyAllowedMergeEventListener() ); - } - - @Test - public void testCascadeFromDetachedToNonDirtyRepresentations() { - Item item1 = new Item(); - item1.setName( "item1" ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - em.persist( item1 ); - em.persist( hoarder ); - em.getTransaction().commit(); - em.close(); - - // Get another representation of the same Item from a different EntityManager. - - em = getOrCreateEntityManager(); - Item item1_1 = em.find( Item.class, item1.getId() ); - em.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Update hoarder (detached) to references both representations. - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - hoarder = em.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - em.getTransaction().commit(); - em.close(); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - hoarder = em.merge( hoarder ); - assertEquals( 1, hoarder.getItems().size() ); - assertSame( hoarder.getFavoriteItem(), hoarder.getItems().iterator().next() ); - assertEquals( item1.getId(), hoarder.getFavoriteItem().getId() ); - assertEquals( item1.getCategory(), hoarder.getFavoriteItem().getCategory() ); - em.getTransaction().commit(); - em.close(); - - cleanup(); - } - - - @Test - public void testTopLevelManyToOneManagedNestedIsDetached() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1 ); - - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - em.persist( item1 ); - em.getTransaction().commit(); - em.close(); - - // get another representation of item1 - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - Item item1_1 = em.find( Item.class, item1.getId() ); - em.getTransaction().commit(); - em.close(); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - Item item1Merged = em.merge( item1 ); - - item1Merged.setCategory( category ); - category.setExampleItem( item1_1 ); - - // now item1Merged is managed and it has a nested detached item - em.merge( item1Merged ); - assertEquals( category.getName(), item1Merged.getCategory().getName() ); - assertSame( item1Merged, item1Merged.getCategory().getExampleItem() ); - em.getTransaction().commit(); - em.close(); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - item1 = em.find( Item.class, item1.getId() ); - assertEquals( category.getName(), item1.getCategory().getName() ); - assertSame( item1, item1.getCategory().getExampleItem() ); - em.getTransaction().commit(); - em.close(); - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - for ( Hoarder hoarder : (List) em.createQuery( "from Hoarder" ).getResultList() ) { - hoarder.getItems().clear(); - em.remove( hoarder ); - } - - for ( Category category : (List) em.createQuery( "from Category" ).getResultList() ) { - if ( category.getExampleItem() != null ) { - category.setExampleItem( null ); - em.remove( category ); - } - } - - for ( Item item : (List) em.createQuery( "from Item" ).getResultList() ) { - item.setCategory( null ); - em.remove( item ); - } - - em.createQuery( "delete from Item" ).executeUpdate(); - - em.getTransaction().commit(); - em.close(); - } - - @Override - public Class[] getAnnotatedClasses() { - return new Class[] { - Category.class, - Hoarder.class, - Item.class - }; - } -} diff --git a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsNotAllowedTest.java b/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsNotAllowedTest.java deleted file mode 100644 index 09432ddcd9..0000000000 --- a/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/emops/MergeMultipleEntityRepresentationsNotAllowedTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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.ejb.test.emops; - -import java.util.List; - -import javax.persistence.EntityManager; - -import org.junit.Test; - -import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.testing.TestForIssue; - -import static junit.framework.TestCase.fail; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * Tests merging multiple detached representations of the same entity using - * a the default MergeEventListener (that does not allow this). - * - * @author Gail Badner - */ -@TestForIssue( jiraKey = "HHH-9106") -public class MergeMultipleEntityRepresentationsNotAllowedTest extends BaseEntityManagerFunctionalTestCase { - - @Test - public void testCascadeFromDetachedToNonDirtyRepresentations() { - Item item1 = new Item(); - item1.setName( "item1" ); - - Hoarder hoarder = new Hoarder(); - hoarder.setName( "joe" ); - - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - em.persist( item1 ); - em.persist( hoarder ); - em.getTransaction().commit(); - em.close(); - - // Get another representation of the same Item from a different session. - - em = getOrCreateEntityManager(); - Item item1_1 = em.find( Item.class, item1.getId() ); - em.close(); - - // item1_1 and item1_2 are unmodified representations of the same persistent entity. - assertFalse( item1 == item1_1 ); - assertTrue( item1.equals( item1_1 ) ); - - // Update hoarder (detached) to references both representations. - hoarder.getItems().add( item1 ); - hoarder.setFavoriteItem( item1_1 ); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - try { - em.merge( hoarder ); - fail( "should have failed due IllegalStateException"); - } - catch (IllegalStateException ex) { - //expected - } - finally { - em.getTransaction().rollback(); - em.close(); - } - - cleanup(); - } - - @Test - public void testTopLevelManyToOneManagedNestedIsDetached() { - Item item1 = new Item(); - item1.setName( "item1 name" ); - Category category = new Category(); - category.setName( "category" ); - item1.setCategory( category ); - category.setExampleItem( item1 ); - - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - em.persist( item1 ); - em.getTransaction().commit(); - em.close(); - - // get another representation of item1 - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - Item item1_1 = em.find( Item.class, item1.getId() ); - em.getTransaction().commit(); - em.close(); - - em = getOrCreateEntityManager(); - em.getTransaction().begin(); - Item item1Merged = em.merge( item1 ); - - item1Merged.setCategory( category ); - category.setExampleItem( item1_1 ); - - // now item1Merged is managed and it has a nested detached item - try { - em.merge( item1Merged ); - fail( "should have failed due IllegalStateException"); - } - catch (IllegalStateException ex) { - //expected - } - finally { - em.getTransaction().rollback(); - em.close(); - } - - cleanup(); - } - - @SuppressWarnings( {"unchecked"}) - private void cleanup() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - for ( Hoarder hoarder : (List) em.createQuery( "from Hoarder" ).getResultList() ) { - hoarder.getItems().clear(); - em.remove( hoarder ); - } - - for ( Category category : (List) em.createQuery( "from Category" ).getResultList() ) { - if ( category.getExampleItem() != null ) { - category.setExampleItem( null ); - em.remove( category ); - } - } - - for ( Item item : (List) em.createQuery( "from Item" ).getResultList() ) { - item.setCategory( null ); - em.remove( item ); - } - - em.createQuery( "delete from Item" ).executeUpdate(); - - em.getTransaction().commit(); - em.close(); - } - - @Override - public Class[] getAnnotatedClasses() { - return new Class[] { - Category.class, - Hoarder.class, - Item.class - }; - } -}