diff --git a/hibernate-core/src/main/java/org/hibernate/engine/spi/BatchFetchQueue.java b/hibernate-core/src/main/java/org/hibernate/engine/spi/BatchFetchQueue.java index 4c000e7613..0afe801f3d 100755 --- a/hibernate-core/src/main/java/org/hibernate/engine/spi/BatchFetchQueue.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/spi/BatchFetchQueue.java @@ -33,6 +33,7 @@ import org.hibernate.EntityMode; import org.hibernate.cache.spi.CacheKey; import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.internal.util.MarkerObject; +import org.hibernate.internal.util.collections.IdentityMap; import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.entity.EntityPersister; @@ -173,12 +174,12 @@ public class BatchFetchQueue { // this only works because collection entries are kept in a sequenced // map by persistence context (maybe we should do like entities and // keep a separate sequences set...) - Iterator iter = context.getCollectionEntries().entrySet().iterator(); //TODO: calling entrySet on an IdentityMap is SLOW!! - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - CollectionEntry ce = (CollectionEntry) me.getValue(); - PersistentCollection collection = (PersistentCollection) me.getKey(); + for ( Map.Entry me : + IdentityMap.concurrentEntries( (Map) context.getCollectionEntries() )) { + + CollectionEntry ce = me.getValue(); + PersistentCollection collection = me.getKey(); if ( !collection.wasInitialized() && ce.getLoadedPersister() == collectionPersister ) { if ( checkForEnd && i == end ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java index 6f1422e8a1..e21bc42a41 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractFlushingEventListener.java @@ -24,7 +24,6 @@ package org.hibernate.event.internal; import java.io.Serializable; -import java.util.Iterator; import java.util.Map; import org.jboss.logging.Logger; @@ -143,12 +142,9 @@ public abstract class AbstractFlushingEventListener implements Serializable { LOG.debug( "Processing flush-time cascades" ); - final Map.Entry[] list = IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ); - //safe from concurrent modification because of how entryList() is implemented on IdentityMap - final int size = list.length; final Object anything = getAnything(); - for ( int i=0; i flushListeners = source .getFactory() @@ -216,13 +205,17 @@ public abstract class AbstractFlushingEventListener implements Serializable { .getEventListenerGroup( EventType.FLUSH_ENTITY ) .listeners(); - final Map.Entry[] list = IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ); - final int size = list.length; - for ( int i = 0; i < size; i++ ) { + // Among other things, updateReachables() will recursively load all + // collections that are moving roles. This might cause entities to + // be loaded. + + // So this needs to be safe from concurrent modification problems. + // It is safe because of how IdentityMap implements entrySet() + + for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) { // Update the status of the object and if necessary, schedule an update - Map.Entry me = list[i]; EntityEntry entry = (EntityEntry) me.getValue(); Status status = entry.getStatus(); @@ -353,11 +346,9 @@ public abstract class AbstractFlushingEventListener implements Serializable { persistenceContext.getBatchFetchQueue() .clearSubselects(); //the database has changed now, so the subselect results need to be invalidated - Iterator iter = persistenceContext.getCollectionEntries().entrySet().iterator(); - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - CollectionEntry collectionEntry = (CollectionEntry) me.getValue(); - PersistentCollection persistentCollection = (PersistentCollection) me.getKey(); + for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getCollectionEntries() ) ) { + CollectionEntry collectionEntry = me.getValue(); + PersistentCollection persistentCollection = me.getKey(); collectionEntry.postFlush(persistentCollection); if ( collectionEntry.getLoadedPersister() == null ) { //if the collection is dereferenced, remove from the session cache diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/IdentityMap.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/IdentityMap.java index 5bbc8d9b0b..1d23c246f9 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/IdentityMap.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/IdentityMap.java @@ -25,13 +25,10 @@ package org.hibernate.internal.util.collections; import java.io.Serializable; -import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; -import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Set;