diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/DetachedMultipleCollectionChangeTest.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/DetachedMultipleCollectionChangeTest.java new file mode 100644 index 0000000000..93916b3d1b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/DetachedMultipleCollectionChangeTest.java @@ -0,0 +1,281 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.event.collection.detached; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.event.spi.AbstractCollectionEvent; +import org.hibernate.event.spi.PostCollectionRecreateEvent; +import org.hibernate.event.spi.PreCollectionRemoveEvent; +import org.hibernate.event.spi.PreCollectionUpdateEvent; +import org.hibernate.test.jpa.AbstractJPATest; +import org.jboss.logging.Logger; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +/** + * Test HHH-6361: Collection events may contain wrong stored snapshot after + * merging a detached entity into the persistencecontext. + * + * @author Erik-Berndt Scheper + */ +public class DetachedMultipleCollectionChangeTest extends AbstractJPATest { + + private final Logger log = Logger + .getLogger(DetachedMultipleCollectionChangeTest.class); + + @Override + public String[] getMappings() { + return new String[] { "event/collection/detached/MultipleCollectionBagMapping.hbm.xml" }; + } + + @Override + protected void cleanupTest() { + Session s = null; + s = openSession(); + s.beginTransaction(); + s.createQuery("delete MultipleCollectionRefEntity1").executeUpdate(); + s.createQuery("delete MultipleCollectionRefEntity2").executeUpdate(); + s.createQuery("delete MultipleCollectionEntity").executeUpdate(); + s.getTransaction().commit(); + s.close(); + } + + @Test + public void testMergeMultipleCollectionChangeEvents() { + MultipleCollectionListeners listeners = new MultipleCollectionListeners( + sessionFactory()); + + List oldRefentities1; + List oldRefentities2; + int eventCount; + Session s; + + oldRefentities1 = new ArrayList(); + oldRefentities2 = new ArrayList(); + + listeners.clear(); + eventCount = 0; + + s = openSession(); + s.beginTransaction(); + + MultipleCollectionEntity mce = new MultipleCollectionEntity(); + mce.setText("MultipleCollectionEntity-1"); + + s.save(mce); + s.getTransaction().commit(); + + checkListener(listeners, listeners.getPreCollectionRecreateListener(), + mce, oldRefentities1, eventCount++); + checkListener(listeners, listeners.getPostCollectionRecreateListener(), + mce, oldRefentities1, eventCount++); + checkListener(listeners, listeners.getPreCollectionRecreateListener(), + mce, oldRefentities2, eventCount++); + checkListener(listeners, listeners.getPostCollectionRecreateListener(), + mce, oldRefentities2, eventCount++); + checkEventCount(listeners, eventCount); + + s.close(); + + Long mceId1 = mce.getId(); + assertNotNull(mceId1); + + // add new entities to both collections + + MultipleCollectionEntity prevMce = mce.deepCopy(); + oldRefentities1 = prevMce.getRefEntities1(); + oldRefentities2 = prevMce.getRefEntities2(); + + listeners.clear(); + eventCount = 0; + + s = openSession(); + s.beginTransaction(); + + MultipleCollectionRefEntity1 re1_1 = new MultipleCollectionRefEntity1(); + re1_1.setText("MultipleCollectionRefEntity1-1"); + re1_1.setMultipleCollectionEntity(mce); + + MultipleCollectionRefEntity1 re1_2 = new MultipleCollectionRefEntity1(); + re1_2.setText("MultipleCollectionRefEntity1-2"); + re1_2.setMultipleCollectionEntity(mce); + + mce.addRefEntity1(re1_1); + mce.addRefEntity1(re1_2); + + mce = (MultipleCollectionEntity) s.merge(mce); + + s.getTransaction().commit(); + s.close(); + + checkListener(listeners, listeners.getInitializeCollectionListener(), + mce, null, eventCount++); + checkListener(listeners, listeners.getPreCollectionUpdateListener(), + mce, oldRefentities1, eventCount++); + checkListener(listeners, listeners.getPostCollectionUpdateListener(), + mce, mce.getRefEntities1(), eventCount++); + + s = openSession(); + s.beginTransaction(); + + MultipleCollectionRefEntity2 re2_1 = new MultipleCollectionRefEntity2(); + re2_1.setText("MultipleCollectionRefEntity2-1"); + re2_1.setMultipleCollectionEntity(mce); + + MultipleCollectionRefEntity2 re2_2 = new MultipleCollectionRefEntity2(); + re2_2.setText("MultipleCollectionRefEntity2-2"); + re2_2.setMultipleCollectionEntity(mce); + + mce.addRefEntity2(re2_1); + mce.addRefEntity2(re2_2); + + mce = (MultipleCollectionEntity) s.merge(mce); + + s.getTransaction().commit(); + + checkListener(listeners, listeners.getInitializeCollectionListener(), + mce, null, eventCount++); + checkListener(listeners, listeners.getPreCollectionUpdateListener(), + mce, oldRefentities2, eventCount++); + checkListener(listeners, listeners.getPostCollectionUpdateListener(), + mce, mce.getRefEntities2(), eventCount++); + checkEventCount(listeners, eventCount); + + s.close(); + + for (MultipleCollectionRefEntity1 refEnt1 : mce.getRefEntities1()) { + assertNotNull(refEnt1.getId()); + } + for (MultipleCollectionRefEntity2 refEnt2 : mce.getRefEntities2()) { + assertNotNull(refEnt2.getId()); + } + + // remove and add entities in both collections + + prevMce = mce.deepCopy(); + oldRefentities1 = prevMce.getRefEntities1(); + oldRefentities2 = prevMce.getRefEntities2(); + + listeners.clear(); + eventCount = 0; + + s = openSession(); + s.beginTransaction(); + + assertEquals(2, mce.getRefEntities1().size()); + assertEquals(2, mce.getRefEntities2().size()); + + mce.removeRefEntity1(re1_2); + + MultipleCollectionRefEntity1 re1_3 = new MultipleCollectionRefEntity1(); + re1_3.setText("MultipleCollectionRefEntity1-3"); + re1_3.setMultipleCollectionEntity(mce); + mce.addRefEntity1(re1_3); + + mce = (MultipleCollectionEntity) s.merge(mce); + + s.getTransaction().commit(); + s.close(); + + checkListener(listeners, listeners.getInitializeCollectionListener(), + mce, null, eventCount++); + checkListener(listeners, listeners.getPreCollectionUpdateListener(), + mce, oldRefentities1, eventCount++); + checkListener(listeners, listeners.getPostCollectionUpdateListener(), + mce, mce.getRefEntities1(), eventCount++); + + s = openSession(); + s.beginTransaction(); + + mce.removeRefEntity2(re2_2); + + MultipleCollectionRefEntity2 re2_3 = new MultipleCollectionRefEntity2(); + re2_3.setText("MultipleCollectionRefEntity2-3"); + re2_3.setMultipleCollectionEntity(mce); + mce.addRefEntity2(re2_3); + + mce = (MultipleCollectionEntity) s.merge(mce); + + // assertEquals(2, mce.getRefEntities1().size()); + // assertEquals(2, mce.getRefEntities2().size()); + + s.getTransaction().commit(); + + checkListener(listeners, listeners.getInitializeCollectionListener(), + mce, null, eventCount++); + checkListener(listeners, listeners.getPreCollectionUpdateListener(), + mce, oldRefentities2, eventCount++); + checkListener(listeners, listeners.getPostCollectionUpdateListener(), + mce, mce.getRefEntities2(), eventCount++); + + checkEventCount(listeners, eventCount); + + s.close(); + } + + protected void checkListener( + MultipleCollectionListeners listeners, + MultipleCollectionListeners.Listener listenerExpected, + org.hibernate.test.event.collection.Entity ownerExpected, + List expectedCollectionEntrySnapshot, + int index) { + AbstractCollectionEvent event = (AbstractCollectionEvent) listeners + .getEvents().get(index); + + assertSame(listenerExpected, listeners.getListenersCalled().get(index)); + assertEquals(ownerExpected, event.getAffectedOwnerOrNull()); + assertEquals(ownerExpected.getId(), event.getAffectedOwnerIdOrNull()); + assertEquals(ownerExpected.getClass().getName(), + event.getAffectedOwnerEntityName()); + + if (event instanceof PreCollectionUpdateEvent) { + Serializable snapshot = listeners.getSnapshots().get(index); + assertEquals(expectedCollectionEntrySnapshot, snapshot); + } + if (event instanceof PreCollectionRemoveEvent) { + Serializable snapshot = listeners.getSnapshots().get(index); + assertEquals(expectedCollectionEntrySnapshot, snapshot); + } + if (event instanceof PostCollectionRecreateEvent) { + Serializable snapshot = listeners.getSnapshots().get(index); + assertEquals(expectedCollectionEntrySnapshot, snapshot); + } + + } + + private void checkEventCount(MultipleCollectionListeners listeners, + int nEventsExpected) { + assertEquals(nEventsExpected, listeners.getListenersCalled().size()); + assertEquals(nEventsExpected, listeners.getEvents().size()); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionBagMapping.hbm.xml b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionBagMapping.hbm.xml new file mode 100644 index 0000000000..3426406f49 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionBagMapping.hbm.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionEntity.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionEntity.java new file mode 100644 index 0000000000..24e055d1fe --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionEntity.java @@ -0,0 +1,168 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.event.collection.detached; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; + +@Entity +public class MultipleCollectionEntity implements org.hibernate.test.event.collection.Entity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", length = 10) + private Long id; + + @Column(name = "TEXT", length = 50, nullable = false) + private String text; + + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "MCE_ID", nullable = false) + private List refEntities1 = new ArrayList(); + + @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "MCE_ID", nullable = false) + private List refEntities2 = new ArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public List getRefEntities1() { + return refEntities1; + } + + public void setRefEntities1(List refEntities1) { + this.refEntities1 = refEntities1; + } + + public void addRefEntity1(MultipleCollectionRefEntity1 refEntity1) { + refEntities1.add(refEntity1); + } + + public void removeRefEntity1(MultipleCollectionRefEntity1 refEntity1) { + refEntities1.remove(refEntity1); + } + + public List getRefEntities2() { + return refEntities2; + } + + public void setRefEntities2(List refEntities2) { + this.refEntities2 = refEntities2; + } + + public void addRefEntity2(MultipleCollectionRefEntity2 refEntity2) { + refEntities2.add(refEntity2); + } + + public void removeRefEntity2(MultipleCollectionRefEntity2 refEntity2) { + refEntities2.remove(refEntity2); + } + + @Override + public String toString() { + return "MultipleCollectionEntity [id=" + id + ", text=" + text + + ", refEntities1=" + refEntities1 + ", refEntities2=" + + refEntities2 + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((text == null) ? 0 : text.hashCode()); + result = prime * result + + ((refEntities1 == null) ? 0 : refEntities1.hashCode()); + result = prime * result + + ((refEntities2 == null) ? 0 : refEntities2.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MultipleCollectionEntity other = (MultipleCollectionEntity) obj; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + if (refEntities1 == null) { + if (other.refEntities1 != null) + return false; + } else if (!refEntities1.equals(other.refEntities1)) + return false; + if (refEntities2 == null) { + if (other.refEntities2 != null) + return false; + } else if (!refEntities2.equals(other.refEntities2)) + return false; + return true; + } + + + public MultipleCollectionEntity deepCopy() { + MultipleCollectionEntity clone = new MultipleCollectionEntity(); + clone.setText(this.text); + clone.setId(this.id); + + for (MultipleCollectionRefEntity1 refEntity1 : refEntities1) { + clone.addRefEntity1(refEntity1.deepCopy(clone)); + } + for (MultipleCollectionRefEntity2 refEntity2 : refEntities2) { + clone.addRefEntity2(refEntity2.deepCopy(clone)); + } + return clone; + } + + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionListeners.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionListeners.java new file mode 100644 index 0000000000..333da328dc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionListeners.java @@ -0,0 +1,265 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.event.collection.detached; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.SessionFactory; +import org.hibernate.engine.spi.CollectionEntry; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.event.internal.DefaultInitializeCollectionEventListener; +import org.hibernate.event.service.spi.EventListenerRegistry; +import org.hibernate.event.spi.AbstractCollectionEvent; +import org.hibernate.event.spi.EventType; +import org.hibernate.event.spi.InitializeCollectionEvent; +import org.hibernate.event.spi.PostCollectionRecreateEvent; +import org.hibernate.event.spi.PostCollectionRecreateEventListener; +import org.hibernate.event.spi.PostCollectionRemoveEvent; +import org.hibernate.event.spi.PostCollectionRemoveEventListener; +import org.hibernate.event.spi.PostCollectionUpdateEvent; +import org.hibernate.event.spi.PostCollectionUpdateEventListener; +import org.hibernate.event.spi.PreCollectionRecreateEvent; +import org.hibernate.event.spi.PreCollectionRecreateEventListener; +import org.hibernate.event.spi.PreCollectionRemoveEvent; +import org.hibernate.event.spi.PreCollectionRemoveEventListener; +import org.hibernate.event.spi.PreCollectionUpdateEvent; +import org.hibernate.event.spi.PreCollectionUpdateEventListener; +import org.jboss.logging.Logger; + +/** + * Support listeners for Test HHH-6361: Collection events may contain wrong + * stored snapshot after merging a detached entity into the persistencecontext. + * + * @author Erik-Berndt Scheper + */ +public class MultipleCollectionListeners { + + private final Logger log = Logger.getLogger(MultipleCollectionListeners.class); + + public interface Listener extends Serializable { + void addEvent(AbstractCollectionEvent event, Listener listener); + } + + public static abstract class AbstractListener implements Listener { + + private final MultipleCollectionListeners listeners; + + protected AbstractListener(MultipleCollectionListeners listeners) { + this.listeners = listeners; + } + + public void addEvent(AbstractCollectionEvent event, Listener listener) { + listeners.addEvent(event, listener); + } + } + + public static class InitializeCollectionListener extends + DefaultInitializeCollectionEventListener implements Listener { + private final MultipleCollectionListeners listeners; + + private InitializeCollectionListener( + MultipleCollectionListeners listeners) { + this.listeners = listeners; + } + + public void onInitializeCollection(InitializeCollectionEvent event) { + super.onInitializeCollection(event); + addEvent(event, this); + } + + public void addEvent(AbstractCollectionEvent event, Listener listener) { + listeners.addEvent(event, listener); + } + } + + public static class PreCollectionRecreateListener extends AbstractListener + implements PreCollectionRecreateEventListener { + private PreCollectionRecreateListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPreRecreateCollection(PreCollectionRecreateEvent event) { + addEvent(event, this); + } + } + + public static class PostCollectionRecreateListener extends AbstractListener + implements PostCollectionRecreateEventListener { + private PostCollectionRecreateListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPostRecreateCollection(PostCollectionRecreateEvent event) { + addEvent(event, this); + } + } + + public static class PreCollectionRemoveListener extends AbstractListener + implements PreCollectionRemoveEventListener { + private PreCollectionRemoveListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPreRemoveCollection(PreCollectionRemoveEvent event) { + addEvent(event, this); + } + } + + public static class PostCollectionRemoveListener extends AbstractListener + implements PostCollectionRemoveEventListener { + private PostCollectionRemoveListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPostRemoveCollection(PostCollectionRemoveEvent event) { + addEvent(event, this); + } + } + + public static class PreCollectionUpdateListener extends AbstractListener + implements PreCollectionUpdateEventListener { + private PreCollectionUpdateListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPreUpdateCollection(PreCollectionUpdateEvent event) { + addEvent(event, this); + } + } + + public static class PostCollectionUpdateListener extends AbstractListener + implements PostCollectionUpdateEventListener { + private PostCollectionUpdateListener( + MultipleCollectionListeners listeners) { + super(listeners); + } + + public void onPostUpdateCollection(PostCollectionUpdateEvent event) { + addEvent(event, this); + } + } + + private final PreCollectionRecreateListener preCollectionRecreateListener; + private final InitializeCollectionListener initializeCollectionListener; + private final PreCollectionRemoveListener preCollectionRemoveListener; + private final PreCollectionUpdateListener preCollectionUpdateListener; + private final PostCollectionRecreateListener postCollectionRecreateListener; + private final PostCollectionRemoveListener postCollectionRemoveListener; + private final PostCollectionUpdateListener postCollectionUpdateListener; + + private List listenersCalled = new ArrayList(); + private List events = new ArrayList(); + private List snapshots = new ArrayList(); + + public MultipleCollectionListeners(SessionFactory sf) { + preCollectionRecreateListener = new PreCollectionRecreateListener(this); + initializeCollectionListener = new InitializeCollectionListener(this); + preCollectionRemoveListener = new PreCollectionRemoveListener(this); + preCollectionUpdateListener = new PreCollectionUpdateListener(this); + postCollectionRecreateListener = new PostCollectionRecreateListener( + this); + postCollectionRemoveListener = new PostCollectionRemoveListener(this); + postCollectionUpdateListener = new PostCollectionUpdateListener(this); + EventListenerRegistry registry = ( (SessionFactoryImplementor) sf ).getServiceRegistry().getService( EventListenerRegistry.class ); + registry.setListeners( EventType.INIT_COLLECTION, initializeCollectionListener ); + + registry.setListeners( EventType.PRE_COLLECTION_RECREATE, preCollectionRecreateListener ); + registry.setListeners( EventType.POST_COLLECTION_RECREATE, postCollectionRecreateListener ); + + registry.setListeners( EventType.PRE_COLLECTION_REMOVE, preCollectionRemoveListener ); + registry.setListeners( EventType.POST_COLLECTION_REMOVE, postCollectionRemoveListener ); + + registry.setListeners( EventType.PRE_COLLECTION_UPDATE, preCollectionUpdateListener ); + registry.setListeners( EventType.POST_COLLECTION_UPDATE, postCollectionUpdateListener ); + } + + public void addEvent(AbstractCollectionEvent event, Listener listener) { + + CollectionEntry collectionEntry = event.getSession() + .getPersistenceContext() + .getCollectionEntry(event.getCollection()); + + Serializable snapshot = collectionEntry.getSnapshot(); + + log.debug("add Event: " + event.getClass() + "; listener = " + + listener.getClass() + "; snapshot = " + snapshot); + + listenersCalled.add(listener); + events.add(event); + snapshots.add(snapshot); + } + + public List getListenersCalled() { + return listenersCalled; + } + + public List getEvents() { + return events; + } + + public List getSnapshots() { + return snapshots; + } + + public void clear() { + listenersCalled.clear(); + events.clear(); + snapshots.clear(); + } + + public PreCollectionRecreateListener getPreCollectionRecreateListener() { + return preCollectionRecreateListener; + } + + public InitializeCollectionListener getInitializeCollectionListener() { + return initializeCollectionListener; + } + + public PreCollectionRemoveListener getPreCollectionRemoveListener() { + return preCollectionRemoveListener; + } + + public PreCollectionUpdateListener getPreCollectionUpdateListener() { + return preCollectionUpdateListener; + } + + public PostCollectionRecreateListener getPostCollectionRecreateListener() { + return postCollectionRecreateListener; + } + + public PostCollectionRemoveListener getPostCollectionRemoveListener() { + return postCollectionRemoveListener; + } + + public PostCollectionUpdateListener getPostCollectionUpdateListener() { + return postCollectionUpdateListener; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java new file mode 100644 index 0000000000..a7e82862fd --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity1.java @@ -0,0 +1,127 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.event.collection.detached; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class MultipleCollectionRefEntity1 implements org.hibernate.test.event.collection.Entity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", length = 10) + private Long id; + + @Column(name = "TEXT", length = 50, nullable = false) + private String text; + + @ManyToOne + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) + @org.hibernate.annotations.ForeignKey(name = "FK_RE1_MCE") + private MultipleCollectionEntity multipleCollectionEntity; + + @Column(name = "MCE_ID", insertable = false, updatable = false) + private Long multipleCollectionEntityId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public MultipleCollectionEntity getMultipleCollectionEntity() { + return multipleCollectionEntity; + } + + public void setMultipleCollectionEntity( + MultipleCollectionEntity multipleCollectionEntity) { + this.multipleCollectionEntity = multipleCollectionEntity; + } + + public Long getMultipleCollectionEntityId() { + return multipleCollectionEntityId; + } + + public void setMultipleCollectionEntityId(Long multipleCollectionEntityId) { + this.multipleCollectionEntityId = multipleCollectionEntityId; + } + + @Override + public String toString() { + return "MultipleCollectionRefEntity1 [id=" + id + ", text=" + text + + ", multipleCollectionEntityId=" + multipleCollectionEntityId + + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((text == null) ? 0 : text.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MultipleCollectionRefEntity1 other = (MultipleCollectionRefEntity1) obj; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + return true; + } + + public MultipleCollectionRefEntity1 deepCopy(MultipleCollectionEntity newRef) { + MultipleCollectionRefEntity1 clone = new MultipleCollectionRefEntity1(); + clone.setText(this.text); + clone.setId(this.id); + clone.setMultipleCollectionEntity(newRef); + clone.setMultipleCollectionEntityId(newRef.getId()); + return clone; + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java new file mode 100644 index 0000000000..eafb2ab82f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/MultipleCollectionRefEntity2.java @@ -0,0 +1,128 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2011, 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.event.collection.detached; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class MultipleCollectionRefEntity2 implements org.hibernate.test.event.collection.Entity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID", length = 10) + private Long id; + + @Column(name = "TEXT", length = 50, nullable = false) + private String text; + + @ManyToOne + @JoinColumn(name = "MCE_ID", nullable = false, insertable = false, updatable = false) + @org.hibernate.annotations.ForeignKey(name = "FK_RE2_MCE") + private MultipleCollectionEntity multipleCollectionEntity; + + @Column(name = "MCE_ID", insertable = false, updatable = false) + private Long multipleCollectionEntityId; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public MultipleCollectionEntity getMultipleCollectionEntity() { + return multipleCollectionEntity; + } + + public void setMultipleCollectionEntity( + MultipleCollectionEntity multipleCollectionEntity) { + this.multipleCollectionEntity = multipleCollectionEntity; + } + + public Long getMultipleCollectionEntityId() { + return multipleCollectionEntityId; + } + + public void setMultipleCollectionEntityId(Long multipleCollectionEntityId) { + this.multipleCollectionEntityId = multipleCollectionEntityId; + } + + @Override + public String toString() { + return "MultipleCollectionRefEntity2 [id=" + id + ", text=" + text + + ", multipleCollectionEntityId=" + multipleCollectionEntityId + + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((text == null) ? 0 : text.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MultipleCollectionRefEntity2 other = (MultipleCollectionRefEntity2) obj; + if (text == null) { + if (other.text != null) + return false; + } else if (!text.equals(other.text)) + return false; + return true; + } + + + public MultipleCollectionRefEntity2 deepCopy(MultipleCollectionEntity newRef) { + MultipleCollectionRefEntity2 clone = new MultipleCollectionRefEntity2(); + clone.setText(this.text); + clone.setId(this.id); + clone.setMultipleCollectionEntity(newRef); + clone.setMultipleCollectionEntityId(newRef.getId()); + return clone; + } + +}