HHH-7928 - Regression caused by HHH-6361
(cherry picked from commit cb1b9a05af
)
Conflicts:
hibernate-core/src/test/java/org/hibernate/test/event/collection/detached/BadMergeHandlingTest.java
This commit is contained in:
parent
603682937c
commit
61f548db6f
|
@ -267,6 +267,8 @@ public final class CollectionEntry implements Serializable {
|
||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean fromMerge = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the stored snapshot for both the persistent collection and this collection entry.
|
* Reset the stored snapshot for both the persistent collection and this collection entry.
|
||||||
* Used during the merge of detached collections.
|
* Used during the merge of detached collections.
|
||||||
|
@ -277,8 +279,13 @@ public final class CollectionEntry implements Serializable {
|
||||||
public void resetStoredSnapshot(PersistentCollection collection, Serializable storedSnapshot) {
|
public void resetStoredSnapshot(PersistentCollection collection, Serializable storedSnapshot) {
|
||||||
LOG.debugf("Reset storedSnapshot to %s for %s", storedSnapshot, this);
|
LOG.debugf("Reset storedSnapshot to %s for %s", storedSnapshot, this);
|
||||||
|
|
||||||
|
if ( fromMerge ) {
|
||||||
|
return; // EARLY EXIT!
|
||||||
|
}
|
||||||
|
|
||||||
snapshot = storedSnapshot;
|
snapshot = storedSnapshot;
|
||||||
collection.setSnapshot(loadedKey, role, snapshot);
|
collection.setSnapshot( loadedKey, role, snapshot );
|
||||||
|
fromMerge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLoadedPersister(CollectionPersister persister) {
|
private void setLoadedPersister(CollectionPersister persister) {
|
||||||
|
|
|
@ -526,15 +526,13 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
// on the target because we simply do not know...
|
// on the target because we simply do not know...
|
||||||
if ( original instanceof PersistentCollection ) {
|
if ( original instanceof PersistentCollection ) {
|
||||||
if ( result instanceof PersistentCollection ) {
|
if ( result instanceof PersistentCollection ) {
|
||||||
if ( ! ( ( PersistentCollection ) original ).isDirty() ) {
|
final PersistentCollection originalPersistentCollection = (PersistentCollection) original;
|
||||||
( ( PersistentCollection ) result ).clearDirty();
|
final PersistentCollection resultPersistentCollection = (PersistentCollection) result;
|
||||||
}
|
|
||||||
|
|
||||||
if ( elemType instanceof AssociationType ) {
|
preserveSnapshot( originalPersistentCollection, resultPersistentCollection, elemType, owner, copyCache, session );
|
||||||
preserveSnapshot( (PersistentCollection) original,
|
|
||||||
(PersistentCollection) result,
|
if ( ! originalPersistentCollection.isDirty() ) {
|
||||||
(AssociationType) elemType, owner, copyCache,
|
resultPersistentCollection.clearDirty();
|
||||||
session );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,9 +540,13 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preserveSnapshot(PersistentCollection original,
|
private void preserveSnapshot(
|
||||||
PersistentCollection result, AssociationType elemType,
|
PersistentCollection original,
|
||||||
Object owner, Map copyCache, SessionImplementor session) {
|
PersistentCollection result,
|
||||||
|
Type elemType,
|
||||||
|
Object owner,
|
||||||
|
Map copyCache,
|
||||||
|
SessionImplementor session) {
|
||||||
Serializable originalSnapshot = original.getStoredSnapshot();
|
Serializable originalSnapshot = original.getStoredSnapshot();
|
||||||
Serializable resultSnapshot = result.getStoredSnapshot();
|
Serializable resultSnapshot = result.getStoredSnapshot();
|
||||||
Serializable targetSnapshot;
|
Serializable targetSnapshot;
|
||||||
|
@ -553,39 +555,35 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
targetSnapshot = new ArrayList(
|
targetSnapshot = new ArrayList(
|
||||||
( (List) originalSnapshot ).size() );
|
( (List) originalSnapshot ).size() );
|
||||||
for ( Object obj : (List) originalSnapshot ) {
|
for ( Object obj : (List) originalSnapshot ) {
|
||||||
( (List) targetSnapshot ).add( elemType.replace(
|
( (List) targetSnapshot ).add( elemType.replace( obj, null, session, owner, copyCache ) );
|
||||||
obj, null, session, owner, copyCache ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( originalSnapshot instanceof Map ) {
|
else if ( originalSnapshot instanceof Map ) {
|
||||||
if ( originalSnapshot instanceof SortedMap ) {
|
if ( originalSnapshot instanceof SortedMap ) {
|
||||||
targetSnapshot = new TreeMap(
|
targetSnapshot = new TreeMap( ( (SortedMap) originalSnapshot ).comparator() );
|
||||||
( (SortedMap) originalSnapshot ).comparator() );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
targetSnapshot = new HashMap(
|
targetSnapshot = new HashMap(
|
||||||
CollectionHelper.determineProperSizing(
|
CollectionHelper.determineProperSizing( ( (Map) originalSnapshot ).size() ),
|
||||||
( (Map) originalSnapshot ).size() ),
|
CollectionHelper.LOAD_FACTOR
|
||||||
CollectionHelper.LOAD_FACTOR );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( Map.Entry<Object, Object> entry : (
|
for ( Map.Entry<Object, Object> entry : ( (Map<Object, Object>) originalSnapshot ).entrySet() ) {
|
||||||
(Map<Object, Object>) originalSnapshot ).entrySet() ) {
|
|
||||||
Object key = entry.getKey();
|
Object key = entry.getKey();
|
||||||
Object value = entry.getValue();
|
Object value = entry.getValue();
|
||||||
Object resultSnapshotValue = ( resultSnapshot == null ) ? null
|
Object resultSnapshotValue = ( resultSnapshot == null )
|
||||||
|
? null
|
||||||
: ( (Map<Object, Object>) resultSnapshot ).get( key );
|
: ( (Map<Object, Object>) resultSnapshot ).get( key );
|
||||||
|
|
||||||
|
Object newValue = elemType.replace( value, resultSnapshotValue, session, owner, copyCache );
|
||||||
|
|
||||||
if ( key == value ) {
|
if ( key == value ) {
|
||||||
Object newValue = elemType.replace( value,
|
|
||||||
resultSnapshotValue, session, owner, copyCache );
|
|
||||||
( (Map) targetSnapshot ).put( newValue, newValue );
|
( (Map) targetSnapshot ).put( newValue, newValue );
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object newValue = elemType.replace( value,
|
|
||||||
resultSnapshotValue, session, owner, copyCache );
|
|
||||||
( (Map) targetSnapshot ).put( key, newValue );
|
( (Map) targetSnapshot ).put( key, newValue );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,8 +593,7 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
else if ( originalSnapshot instanceof Object[] ) {
|
else if ( originalSnapshot instanceof Object[] ) {
|
||||||
Object[] arr = (Object[]) originalSnapshot;
|
Object[] arr = (Object[]) originalSnapshot;
|
||||||
for ( int i = 0; i < arr.length; i++ ) {
|
for ( int i = 0; i < arr.length; i++ ) {
|
||||||
arr[i] = elemType.replace(
|
arr[i] = elemType.replace( arr[i], null, session, owner, copyCache );
|
||||||
arr[i], null, session, owner, copyCache );
|
|
||||||
}
|
}
|
||||||
targetSnapshot = originalSnapshot;
|
targetSnapshot = originalSnapshot;
|
||||||
|
|
||||||
|
@ -607,8 +604,7 @@ public abstract class CollectionType extends AbstractType implements Association
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(
|
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( result );
|
||||||
result );
|
|
||||||
if ( ce != null ) {
|
if ( ce != null ) {
|
||||||
ce.resetStoredSnapshot( result, targetSnapshot );
|
ce.resetStoredSnapshot( result, targetSnapshot );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, 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.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
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.InitializeCollectionEventListener;
|
||||||
|
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.hibernate.integrator.spi.Integrator;
|
||||||
|
import org.hibernate.metamodel.source.MetadataImplementor;
|
||||||
|
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
* @author Gail Badner
|
||||||
|
*/
|
||||||
|
public class AggregatedCollectionEventListener
|
||||||
|
implements InitializeCollectionEventListener,
|
||||||
|
PreCollectionRecreateEventListener,
|
||||||
|
PostCollectionRecreateEventListener,
|
||||||
|
PreCollectionRemoveEventListener,
|
||||||
|
PostCollectionRemoveEventListener,
|
||||||
|
PreCollectionUpdateEventListener,
|
||||||
|
PostCollectionUpdateEventListener {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger( AggregatedCollectionEventListener.class );
|
||||||
|
|
||||||
|
private final List<EventEntry> eventEntryList = new ArrayList<EventEntry>();
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
eventEntryList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<EventEntry> getEventEntryList() {
|
||||||
|
return eventEntryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeCollection(InitializeCollectionEvent event) throws HibernateException {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addEvent(AbstractCollectionEvent event) {
|
||||||
|
log.debugf( "Added collection event : %s", event );
|
||||||
|
eventEntryList.add( new EventEntry( event ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// recreate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreRecreateCollection(PreCollectionRecreateEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// remove ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
|
||||||
|
addEvent( event );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EventEntry {
|
||||||
|
private final AbstractCollectionEvent event;
|
||||||
|
private final Serializable snapshotAtTimeOfEventHandling;
|
||||||
|
|
||||||
|
public EventEntry(AbstractCollectionEvent event) {
|
||||||
|
this.event = event;
|
||||||
|
// make a copy of the collection?
|
||||||
|
this.snapshotAtTimeOfEventHandling = event.getSession()
|
||||||
|
.getPersistenceContext()
|
||||||
|
.getCollectionEntry( event.getCollection() )
|
||||||
|
.getSnapshot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractCollectionEvent getEvent() {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Serializable getSnapshotAtTimeOfEventHandling() {
|
||||||
|
return snapshotAtTimeOfEventHandling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class IntegratorImpl implements Integrator {
|
||||||
|
private AggregatedCollectionEventListener listener;
|
||||||
|
|
||||||
|
public AggregatedCollectionEventListener getListener() {
|
||||||
|
if ( listener == null ) {
|
||||||
|
throw new HibernateException( "Integrator not yet processed" );
|
||||||
|
}
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void integrate(
|
||||||
|
Configuration configuration,
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
integrate( serviceRegistry );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void integrate(SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
if ( listener != null ) {
|
||||||
|
log.warn( "integrate called second time on testing collection listener Integrator (could be result of rebuilding SF on test failure)" );
|
||||||
|
}
|
||||||
|
listener = new AggregatedCollectionEventListener();
|
||||||
|
|
||||||
|
final EventListenerRegistry listenerRegistry = serviceRegistry.getService( EventListenerRegistry.class );
|
||||||
|
listenerRegistry.appendListeners( EventType.INIT_COLLECTION, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.PRE_COLLECTION_RECREATE, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.POST_COLLECTION_RECREATE, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.PRE_COLLECTION_REMOVE, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.POST_COLLECTION_REMOVE, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.PRE_COLLECTION_UPDATE, listener );
|
||||||
|
listenerRegistry.appendListeners( EventType.POST_COLLECTION_UPDATE, listener );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void integrate(
|
||||||
|
MetadataImplementor metadata,
|
||||||
|
SessionFactoryImplementor sessionFactory,
|
||||||
|
SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
integrate( serviceRegistry );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disintegrate(
|
||||||
|
SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, 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.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Alias implements Identifiable {
|
||||||
|
private Integer id;
|
||||||
|
private String alias;
|
||||||
|
private List<Character> characters = new ArrayList<Character>();
|
||||||
|
|
||||||
|
public Alias() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Alias(Integer id, String alias) {
|
||||||
|
this.id = id;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Override
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlias(String alias) {
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToMany( cascade = CascadeType.ALL )
|
||||||
|
@JoinTable( name = "CHARACTER_ALIAS" )
|
||||||
|
// @JoinTable(
|
||||||
|
// name = "CHARACTER_ALIAS",
|
||||||
|
// joinColumns = @JoinColumn(name="ALIAS_ID", referencedColumnName="ID"),
|
||||||
|
// inverseJoinColumns = @JoinColumn(name="CHARACTER_ID", referencedColumnName="ID")
|
||||||
|
// )
|
||||||
|
public List<Character> getCharacters() {
|
||||||
|
return characters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCharacters(List<Character> characters) {
|
||||||
|
this.characters = characters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,17 +23,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.event.collection.detached;
|
package org.hibernate.test.event.collection.detached;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.JoinColumn;
|
|
||||||
import javax.persistence.JoinTable;
|
|
||||||
import javax.persistence.ManyToMany;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
@ -53,7 +42,7 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class[] { Customer.class, Alias.class, CreditCard.class };
|
return new Class[] { Character.class, Alias.class };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -61,10 +50,11 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
public void testMergeAndHold() {
|
public void testMergeAndHold() {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
Customer paul = new Customer( 1, "Paul Atreides" );
|
|
||||||
|
Character paul = new Character( 1, "Paul Atreides" );
|
||||||
s.persist( paul );
|
s.persist( paul );
|
||||||
Customer duke = new Customer( 2, "Duke Leto" );
|
Character paulo = new Character( 2, "Paulo Atreides" );
|
||||||
s.persist( duke );
|
s.persist( paulo );
|
||||||
|
|
||||||
Alias alias1 = new Alias( 1, "Paul Muad'Dib" );
|
Alias alias1 = new Alias( 1, "Paul Muad'Dib" );
|
||||||
s.persist( alias1 );
|
s.persist( alias1 );
|
||||||
|
@ -75,12 +65,6 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
Alias alias3 = new Alias( 3, "The Preacher" );
|
Alias alias3 = new Alias( 3, "The Preacher" );
|
||||||
s.persist( alias3 );
|
s.persist( alias3 );
|
||||||
|
|
||||||
CreditCard cc1 = new CreditCard( 1 );
|
|
||||||
s.persist( cc1 );
|
|
||||||
|
|
||||||
CreditCard cc2 = new CreditCard( 2 );
|
|
||||||
s.persist( cc2 );
|
|
||||||
|
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
|
@ -88,29 +72,24 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
s = openSession();
|
s = openSession();
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
|
|
||||||
// customer 1
|
// customer 1
|
||||||
alias1.customers.add( paul );
|
alias1.getCharacters().add( paul );
|
||||||
s.merge( alias1 );
|
s.merge( alias1 );
|
||||||
alias2.customers.add( paul );
|
alias2.getCharacters().add( paul );
|
||||||
s.merge( alias2 );
|
s.merge( alias2 );
|
||||||
alias3.customers.add( paul );
|
alias3.getCharacters().add( paul );
|
||||||
s.merge( alias3 );
|
s.merge( alias3 );
|
||||||
|
|
||||||
s.flush();
|
s.flush();
|
||||||
|
|
||||||
// customer 2
|
// customer 2
|
||||||
alias1.customers.add( duke );
|
alias1.getCharacters().add( paulo );
|
||||||
s.merge( alias1 );
|
s.merge( alias1 );
|
||||||
alias2.customers.add( duke );
|
alias2.getCharacters().add( paulo );
|
||||||
s.merge( alias2 );
|
s.merge( alias2 );
|
||||||
alias3.customers.add( duke );
|
alias3.getCharacters().add( paulo );
|
||||||
s.merge( alias3 );
|
s.merge( alias3 );
|
||||||
s.flush();
|
s.flush();
|
||||||
|
|
||||||
cc1.customer = paul;
|
|
||||||
s.merge( cc1 );
|
|
||||||
cc2.customer = paul;
|
|
||||||
s.merge( cc2 );
|
|
||||||
|
|
||||||
s.getTransaction().commit();
|
s.getTransaction().commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
@ -118,7 +97,7 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
// now try to read them back (I guess)
|
// now try to read them back (I guess)
|
||||||
s = openSession();
|
s = openSession();
|
||||||
s.beginTransaction();
|
s.beginTransaction();
|
||||||
List results = s.createQuery( "select c from Customer c join c.aliases a where a.alias = :aParam" )
|
List results = s.createQuery( "select c from Character c join c.aliases a where a.alias = :aParam" )
|
||||||
.setParameter( "aParam", "Usul" )
|
.setParameter( "aParam", "Usul" )
|
||||||
.list();
|
.list();
|
||||||
assertEquals( 2, results.size() );
|
assertEquals( 2, results.size() );
|
||||||
|
@ -126,63 +105,4 @@ public class BadMergeHandlingTest extends BaseCoreFunctionalTestCase {
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity( name="Customer" )
|
|
||||||
public static class Customer {
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
private String name;
|
|
||||||
@ManyToMany( cascade= CascadeType.ALL, mappedBy="customers" )
|
|
||||||
private Collection<Alias> aliases = new ArrayList<Alias>();
|
|
||||||
@OneToMany(cascade=CascadeType.ALL, mappedBy="customer")
|
|
||||||
private Collection<CreditCard> creditCards = new ArrayList<CreditCard>();
|
|
||||||
|
|
||||||
public Customer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Customer(Integer id, String name) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity( name="Alias" )
|
|
||||||
public static class Alias {
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
private String alias;
|
|
||||||
@ManyToMany(cascade=CascadeType.ALL)
|
|
||||||
@JoinTable(name="FKS_ALIAS_CUSTOMER",
|
|
||||||
joinColumns=
|
|
||||||
@JoinColumn(
|
|
||||||
name="FK_FOR_ALIAS_TABLE", referencedColumnName="ID"),
|
|
||||||
inverseJoinColumns=
|
|
||||||
@JoinColumn(
|
|
||||||
name="FK_FOR_CUSTOMER_TABLE", referencedColumnName="ID")
|
|
||||||
)
|
|
||||||
private Collection<Customer> customers = new ArrayList<Customer>();
|
|
||||||
|
|
||||||
public Alias() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Alias(Integer id, String alias) {
|
|
||||||
this.id = id;
|
|
||||||
this.alias = alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity( name="CreditCard" )
|
|
||||||
public static class CreditCard {
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
@ManyToOne(cascade=CascadeType.ALL)
|
|
||||||
@JoinColumn (name="FK3_FOR_CUSTOMER_TABLE")
|
|
||||||
private Customer customer;
|
|
||||||
|
|
||||||
public CreditCard() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public CreditCard(Integer id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, 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.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Character implements Identifiable {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private List<Alias> aliases = new ArrayList<Alias>();
|
||||||
|
|
||||||
|
public Character() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Character(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Override
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManyToMany( cascade= CascadeType.ALL, mappedBy="characters" )
|
||||||
|
public List<Alias> getAliases() {
|
||||||
|
return aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAliases(List<Alias> aliases) {
|
||||||
|
this.aliases = aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void associateAlias(Alias alias) {
|
||||||
|
alias.getCharacters().add( this );
|
||||||
|
getAliases().add( alias );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public interface Identifiable {
|
||||||
|
public Integer getId();
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, 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.Collections;
|
||||||
|
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.PostCollectionUpdateEvent;
|
||||||
|
import org.hibernate.event.spi.PreCollectionRecreateEvent;
|
||||||
|
import org.hibernate.event.spi.PreCollectionRemoveEvent;
|
||||||
|
import org.hibernate.event.spi.PreCollectionUpdateEvent;
|
||||||
|
import org.hibernate.service.BootstrapServiceRegistryBuilder;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@TestForIssue( jiraKey = "HHH-7928" )
|
||||||
|
public class MergeCollectionEventTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private AggregatedCollectionEventListener.IntegratorImpl collectionListenerIntegrator =
|
||||||
|
new AggregatedCollectionEventListener.IntegratorImpl();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void resetListener() {
|
||||||
|
collectionListenerIntegrator.getListener().reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { Character.class, Alias.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
|
||||||
|
super.prepareBootstrapRegistryBuilder( builder );
|
||||||
|
builder.with( collectionListenerIntegrator );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanupTestData() throws Exception {
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
List<Alias> aliases = s.createQuery( "from Alias" ).list();
|
||||||
|
for ( Alias alias : aliases ) {
|
||||||
|
for ( Character character : alias.getCharacters() ) {
|
||||||
|
character.getAliases().clear();
|
||||||
|
}
|
||||||
|
alias.getCharacters().clear();
|
||||||
|
}
|
||||||
|
s.flush();
|
||||||
|
s.createQuery( "delete Alias" ).executeUpdate();
|
||||||
|
s.createQuery( "delete Character" ).executeUpdate();
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectionEventHandlingOnMerge() {
|
||||||
|
final AggregatedCollectionEventListener listener = collectionListenerIntegrator.getListener();
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// This first bit really is just preparing the entities. There is generally no collection
|
||||||
|
// events of real interest during this part
|
||||||
|
|
||||||
|
Session s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Character paul = new Character( 1, "Paul Atreides" );
|
||||||
|
s.save( paul );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertEquals( 2, listener.getEventEntryList().size() );
|
||||||
|
checkListener( 0, PreCollectionRecreateEvent.class, paul, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 1, PostCollectionRecreateEvent.class, paul, Collections.EMPTY_LIST );
|
||||||
|
|
||||||
|
listener.reset();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Character paulo = new Character( 2, "Paulo Atreides" );
|
||||||
|
s.save( paulo );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertEquals( 2, listener.getEventEntryList().size() );
|
||||||
|
checkListener( 0, PreCollectionRecreateEvent.class, paulo, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 1, PostCollectionRecreateEvent.class, paulo, Collections.EMPTY_LIST );
|
||||||
|
|
||||||
|
listener.reset();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Alias alias1 = new Alias( 1, "Paul Muad'Dib" );
|
||||||
|
s.save( alias1 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertEquals( 2, listener.getEventEntryList().size() );
|
||||||
|
checkListener( 0, PreCollectionRecreateEvent.class, alias1, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 1, PostCollectionRecreateEvent.class, alias1, Collections.EMPTY_LIST );
|
||||||
|
|
||||||
|
listener.reset();
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
Alias alias2 = new Alias( 2, "Usul" );
|
||||||
|
s.save( alias2 );
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
|
||||||
|
assertEquals( 2, listener.getEventEntryList().size() );
|
||||||
|
checkListener( 0, PreCollectionRecreateEvent.class, alias2, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 1, PostCollectionRecreateEvent.class, alias2, Collections.EMPTY_LIST );
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// at this point we can start setting up the associations and checking collection events
|
||||||
|
// of "real interest"
|
||||||
|
|
||||||
|
listener.reset();
|
||||||
|
|
||||||
|
paul.associateAlias( alias1 );
|
||||||
|
paul.associateAlias( alias2 );
|
||||||
|
|
||||||
|
paulo.associateAlias( alias1 );
|
||||||
|
paulo.associateAlias( alias2 );
|
||||||
|
|
||||||
|
s = openSession();
|
||||||
|
s.beginTransaction();
|
||||||
|
s.merge( alias1 );
|
||||||
|
|
||||||
|
assertEquals( 0, listener.getEventEntryList().size() );
|
||||||
|
|
||||||
|
// this is where HHH-7928 (problem with HHH-6361 fix) shows up...
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
assertEquals( 8, listener.getEventEntryList().size() ); // 4 collections x 2 events per
|
||||||
|
checkListener( 0, PreCollectionUpdateEvent.class, alias1, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 1, PostCollectionUpdateEvent.class, alias1, alias1.getCharacters() );
|
||||||
|
checkListener( 2, PreCollectionUpdateEvent.class, paul, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 3, PostCollectionUpdateEvent.class, paul, paul.getAliases() );
|
||||||
|
checkListener( 4, PreCollectionUpdateEvent.class, alias2, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 5, PostCollectionUpdateEvent.class, alias2, alias2.getCharacters() );
|
||||||
|
checkListener( 6, PreCollectionUpdateEvent.class, paulo, Collections.EMPTY_LIST );
|
||||||
|
checkListener( 7, PostCollectionUpdateEvent.class, paulo, paul.getAliases() );
|
||||||
|
|
||||||
|
List<Character> alias1CharactersSnapshot = copy( alias1.getCharacters() );
|
||||||
|
List<Character> alias2CharactersSnapshot = copy( alias2.getCharacters() );
|
||||||
|
|
||||||
|
listener.reset();
|
||||||
|
|
||||||
|
s.merge( alias2 );
|
||||||
|
|
||||||
|
assertEquals( 0, listener.getEventEntryList().size() );
|
||||||
|
|
||||||
|
s.flush();
|
||||||
|
|
||||||
|
assertEquals( 8, listener.getEventEntryList().size() ); // 4 collections x 2 events per
|
||||||
|
checkListener( 0, PreCollectionUpdateEvent.class, alias1, alias1CharactersSnapshot );
|
||||||
|
checkListener( 1, PostCollectionUpdateEvent.class, alias1, alias1CharactersSnapshot );
|
||||||
|
// checkListener( 2, PreCollectionUpdateEvent.class, paul, Collections.EMPTY_LIST );
|
||||||
|
// checkListener( 3, PostCollectionUpdateEvent.class, paul, paul.getAliases() );
|
||||||
|
checkListener( 4, PreCollectionUpdateEvent.class, alias2, alias2CharactersSnapshot );
|
||||||
|
checkListener( 5, PostCollectionUpdateEvent.class, alias2, alias2.getCharacters() );
|
||||||
|
// checkListener( 6, PreCollectionUpdateEvent.class, paulo, Collections.EMPTY_LIST );
|
||||||
|
// checkListener( 7, PostCollectionUpdateEvent.class, paulo, paul.getAliases() );
|
||||||
|
|
||||||
|
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++);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void checkListener(
|
||||||
|
int eventIndex,
|
||||||
|
Class<? extends AbstractCollectionEvent> expectedEventType,
|
||||||
|
Identifiable expectedOwner,
|
||||||
|
List<? extends Identifiable> expectedCollectionEntrySnapshot) {
|
||||||
|
final AggregatedCollectionEventListener.EventEntry eventEntry
|
||||||
|
= collectionListenerIntegrator.getListener().getEventEntryList().get( eventIndex );
|
||||||
|
final AbstractCollectionEvent event = eventEntry.getEvent();
|
||||||
|
|
||||||
|
assertTyping( expectedEventType, event );
|
||||||
|
|
||||||
|
// because of the merge graphs, the instances are likely different. just base check on type and id
|
||||||
|
// assertEquals( expectedOwner, event.getAffectedOwnerOrNull() );
|
||||||
|
assertEquals( expectedOwner.getClass().getName(), event.getAffectedOwnerEntityName() );
|
||||||
|
assertEquals( expectedOwner.getId(), event.getAffectedOwnerIdOrNull() );
|
||||||
|
|
||||||
|
if ( event instanceof PreCollectionUpdateEvent
|
||||||
|
|| event instanceof PreCollectionRemoveEvent
|
||||||
|
|| event instanceof PostCollectionRecreateEvent ) {
|
||||||
|
List<Identifiable> snapshot = (List) eventEntry.getSnapshotAtTimeOfEventHandling();
|
||||||
|
assertEquals( expectedCollectionEntrySnapshot.size(), snapshot.size() );
|
||||||
|
for ( int i = 0; i < expectedCollectionEntrySnapshot.size(); i++ ) {
|
||||||
|
Identifiable expected = expectedCollectionEntrySnapshot.get( i );
|
||||||
|
Identifiable found = snapshot.get( i );
|
||||||
|
assertEquals( expected.getClass().getName(), found.getClass().getName() );
|
||||||
|
assertEquals( expected.getId(), found.getId() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> List<T> copy(List<T> source) {
|
||||||
|
ArrayList<T> copy = new ArrayList<T>( source.size() );
|
||||||
|
copy.addAll( source );
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -203,10 +203,10 @@ public class MultipleCollectionListeners {
|
||||||
|
|
||||||
public void addEvent(AbstractCollectionEvent event, Listener listener) {
|
public void addEvent(AbstractCollectionEvent event, Listener listener) {
|
||||||
|
|
||||||
|
|
||||||
CollectionEntry collectionEntry = event.getSession()
|
CollectionEntry collectionEntry = event.getSession()
|
||||||
.getPersistenceContext()
|
.getPersistenceContext()
|
||||||
.getCollectionEntry(event.getCollection());
|
.getCollectionEntry(event.getCollection());
|
||||||
|
|
||||||
Serializable snapshot = collectionEntry.getSnapshot();
|
Serializable snapshot = collectionEntry.getSnapshot();
|
||||||
|
|
||||||
log.debug("add Event: " + event.getClass() + "; listener = "
|
log.debug("add Event: " + event.getClass() + "; listener = "
|
||||||
|
|
Loading…
Reference in New Issue