[hibernate-commits] Hibernate SVN: r11301 - in branches/Branch_3_2/Hibernate3/src/org/hibernate: engine and 3 other directories.
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Mon Mar 19 16:43:47 EDT 2007
Author: steve.ebersole at jboss.com
Date: 2007-03-19 16:43:46 -0400 (Mon, 19 Mar 2007)
New Revision: 11301
Added:
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/EntityLoadContext.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadContexts.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadingCollectionEntry.java
Removed:
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java
Modified:
branches/Branch_3_2/Hibernate3/src/org/hibernate/collection/AbstractPersistentCollection.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/PersistenceContext.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/StatefulPersistenceContext.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/Loader.java
branches/Branch_3_2/Hibernate3/src/org/hibernate/type/CollectionType.java
Log:
HHH-2495 : ResultSet processing context
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/collection/AbstractPersistentCollection.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/collection/AbstractPersistentCollection.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/collection/AbstractPersistentCollection.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -538,7 +538,7 @@
/**
* Get the current session
*/
- protected final SessionImplementor getSession() {
+ public final SessionImplementor getSession() {
return session;
}
Deleted: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/CollectionLoadContext.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -1,340 +0,0 @@
-//$Id$
-package org.hibernate.engine;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.hibernate.CacheMode;
-import org.hibernate.EntityMode;
-import org.hibernate.HibernateException;
-import org.hibernate.cache.CacheKey;
-import org.hibernate.cache.entry.CollectionCacheEntry;
-import org.hibernate.collection.PersistentCollection;
-import org.hibernate.persister.collection.CollectionPersister;
-import org.hibernate.pretty.MessageHelper;
-
-/**
- * Represents the state of collections currently being loaded. Eventually, I
- * would like to have multiple instances of this per session - one per JDBC
- * result set, instead of the resultSetId being passed.
- * @author Gavin King
- */
-public class CollectionLoadContext {
-
- private static final Log log = LogFactory.getLog(CollectionLoadContext.class);
-
- // The collections we are currently loading
- private final Map loadingCollections = new HashMap(8);
- private final PersistenceContext context;
-
- public CollectionLoadContext(PersistenceContext context) {
- this.context = context;
- }
-
- private static final class LoadingCollectionEntry {
-
- final PersistentCollection collection;
- final Serializable key;
- final Object resultSetId;
- final CollectionPersister persister;
-
- LoadingCollectionEntry(
- final PersistentCollection collection,
- final Serializable key,
- final CollectionPersister persister,
- final Object resultSetId
- ) {
- this.collection = collection;
- this.key = key;
- this.persister = persister;
- this.resultSetId = resultSetId;
- }
- }
-
- /**
- * Retrieve a collection that is in the process of being loaded, instantiating
- * a new collection if there is nothing for the given id, or returning null
- * if the collection with the given id is already fully loaded in the session
- */
- public PersistentCollection getLoadingCollection(
- final CollectionPersister persister,
- final Serializable key,
- final Object resultSetId,
- final EntityMode em)
- throws HibernateException {
- CollectionKey ckey = new CollectionKey(persister, key, em);
- LoadingCollectionEntry lce = getLoadingCollectionEntry(ckey);
- if ( lce == null ) {
- //look for existing collection
- PersistentCollection collection = context.getCollection(ckey);
- if ( collection != null ) {
- if ( collection.wasInitialized() ) {
- log.trace( "collection already initialized: ignoring" );
- return null; //ignore this row of results! Note the early exit
- }
- else {
- //initialize this collection
- log.trace( "uninitialized collection: initializing" );
- }
- }
- else {
- Object entity = context.getCollectionOwner(key, persister);
- final boolean newlySavedEntity = entity != null &&
- context.getEntry(entity).getStatus() != Status.LOADING &&
- em!=EntityMode.DOM4J;
- if ( newlySavedEntity ) {
- //important, to account for newly saved entities in query
- //TODO: some kind of check for new status...
- log.trace( "owning entity already loaded: ignoring" );
- return null;
- }
- else {
- //create one
- log.trace( "new collection: instantiating" );
- collection = persister.getCollectionType()
- .instantiate( context.getSession(), persister, key );
- }
- }
- collection.beforeInitialize( persister, -1 );
- collection.beginRead();
- addLoadingCollectionEntry(ckey, collection, persister, resultSetId);
- return collection;
- }
- else {
- if ( lce.resultSetId == resultSetId ) {
- log.trace( "reading row" );
- return lce.collection;
- }
- else {
- // ignore this row, the collection is in process of
- // being loaded somewhere further "up" the stack
- log.trace( "collection is already being initialized: ignoring row" );
- return null;
- }
- }
- }
-
- /**
- * Retrieve a collection that is in the process of being loaded, returning null
- * if there is no loading collection with the given id
- */
- public PersistentCollection getLoadingCollection(CollectionPersister persister, Serializable id, EntityMode em) {
- LoadingCollectionEntry lce = getLoadingCollectionEntry( new CollectionKey(persister, id, em) );
- if ( lce != null ) {
- if ( log.isTraceEnabled() ) {
- log.trace(
- "returning loading collection:" +
- MessageHelper.collectionInfoString(persister, id, context.getSession().getFactory())
- );
- }
- return lce.collection;
- }
- else {
- if ( log.isTraceEnabled() ) {
- log.trace(
- "creating collection wrapper:" +
- MessageHelper.collectionInfoString(persister, id, context.getSession().getFactory())
- );
- }
- return null;
- }
- }
-
- /**
- * Create a new loading collection entry
- */
- private void addLoadingCollectionEntry(
- final CollectionKey collectionKey,
- final PersistentCollection collection,
- final CollectionPersister persister,
- final Object resultSetId
- ) {
- loadingCollections.put(
- collectionKey,
- new LoadingCollectionEntry(
- collection,
- collectionKey.getKey(),
- persister,
- resultSetId
- )
- );
- }
-
- /**
- * get an existing new loading collection entry
- */
- private LoadingCollectionEntry getLoadingCollectionEntry(CollectionKey collectionKey) {
- return ( LoadingCollectionEntry ) loadingCollections.get( collectionKey );
- }
-
- /**
- * After we have finished processing a result set, a particular loading collection that
- * we are done.
- */
- private void endLoadingCollection(LoadingCollectionEntry lce, CollectionPersister persister, EntityMode em) {
-
- boolean hasNoQueuedAdds = lce.collection.endRead(); //warning: can cause a recursive query! (proxy initialization)
-
- if ( persister.getCollectionType().hasHolder(em) ) {
- context.addCollectionHolder(lce.collection);
- }
-
- CollectionEntry ce = context.getCollectionEntry(lce.collection);
- if ( ce==null ) {
- ce = context.addInitializedCollection(persister, lce.collection, lce.key);
- }
- else {
- ce.postInitialize(lce.collection);
- }
-
- final SessionImplementor session = context.getSession();
-
- boolean addToCache = hasNoQueuedAdds && // there were no queued additions
- persister.hasCache() && // and the role has a cache
- session.getCacheMode().isPutEnabled() &&
- !ce.isDoremove(); // and this is not a forced initialization during flush
- if (addToCache) addCollectionToCache(lce, persister);
-
- if ( log.isDebugEnabled() ) {
- log.debug(
- "collection fully initialized: " +
- MessageHelper.collectionInfoString(persister, lce.key, context.getSession().getFactory())
- );
- }
-
- if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
- session.getFactory().getStatisticsImplementor().loadCollection(
- persister.getRole()
- );
- }
-
- }
- /**
- * Finish the process of loading collections for a particular result set
- */
- public void endLoadingCollections(CollectionPersister persister, Object resultSetId, SessionImplementor session)
- throws HibernateException {
-
- // scan the loading collections for collections from this result set
- // put them in a new temp collection so that we are safe from concurrent
- // modification when the call to endRead() causes a proxy to be
- // initialized
- List resultSetCollections = null; //TODO: make this the resultSetId?
- Iterator iter = loadingCollections.values().iterator();
- while ( iter.hasNext() ) {
- LoadingCollectionEntry lce = (LoadingCollectionEntry) iter.next();
- if ( lce.resultSetId == resultSetId && lce.persister==persister) {
- if ( resultSetCollections == null ) {
- resultSetCollections = new ArrayList();
- }
- resultSetCollections.add(lce);
- if ( lce.collection.getOwner()==null ) {
- session.getPersistenceContext()
- .addUnownedCollection(
- new CollectionKey( persister, lce.key, session.getEntityMode() ),
- lce.collection
- );
- }
- iter.remove();
- }
- }
-
- endLoadingCollections( persister, resultSetCollections, session.getEntityMode() );
- }
-
- /**
- * After we have finished processing a result set, notify the loading collections that
- * we are done.
- */
- private void endLoadingCollections(CollectionPersister persister, List resultSetCollections, EntityMode em)
- throws HibernateException {
-
- final int count = (resultSetCollections == null) ? 0 : resultSetCollections.size();
-
- if ( log.isDebugEnabled() ) {
- log.debug( count + " collections were found in result set for role: " + persister.getRole() );
- }
-
- //now finish them
- for ( int i = 0; i < count; i++ ) {
- LoadingCollectionEntry lce = (LoadingCollectionEntry) resultSetCollections.get(i);
- endLoadingCollection(lce, persister, em);
- }
-
- if ( log.isDebugEnabled() ) {
- log.debug( count + " collections initialized for role: " + persister.getRole() );
- }
- }
-
- /**
- * Add a collection to the second-level cache
- */
- private void addCollectionToCache(LoadingCollectionEntry lce, CollectionPersister persister) {
-
- if ( log.isDebugEnabled() ) {
- log.debug(
- "Caching collection: " +
- MessageHelper.collectionInfoString( persister, lce.key, context.getSession().getFactory() )
- );
- }
-
- final SessionImplementor session = context.getSession();
- final SessionFactoryImplementor factory = session.getFactory();
-
- if ( !session.getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters( session ) ) {
- // some filters affecting the collection are enabled on the session, so do not do the put into the cache.
- log.debug( "Refusing to add to cache due to enabled filters" );
- // todo : add the notion of enabled filters to the CacheKey to differentiate filtered collections from non-filtered;
- // but CacheKey is currently used for both collections and entities; would ideally need to define two seperate ones;
- // currently this works in conjuction with the check on
- // DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
- // cache with enabled filters).
- return; // EARLY EXIT!!!!!
- }
-
- final Comparator versionComparator;
- final Object version;
- if ( persister.isVersioned() ) {
- versionComparator = persister.getOwnerEntityPersister().getVersionType().getComparator();
- version = context.getEntry( context.getCollectionOwner(lce.key, persister) ).getVersion();
- }
- else {
- version = null;
- versionComparator = null;
- }
-
- CollectionCacheEntry entry = new CollectionCacheEntry(lce.collection, persister);
-
- CacheKey cacheKey = new CacheKey(
- lce.key,
- persister.getKeyType(),
- persister.getRole(),
- session.getEntityMode(),
- session.getFactory()
- );
- boolean put = persister.getCache().put(
- cacheKey,
- persister.getCacheEntryStructure().structure(entry),
- session.getTimestamp(),
- version,
- versionComparator,
- factory.getSettings().isMinimalPutsEnabled() &&
- session.getCacheMode()!=CacheMode.REFRESH
- );
-
- if ( put && factory.getStatistics().isStatisticsEnabled() ) {
- factory.getStatisticsImplementor().secondLevelCachePut(
- persister.getCache().getRegionName()
- );
- }
- }
-
-
-}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/PersistenceContext.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/PersistenceContext.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/PersistenceContext.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -8,6 +8,7 @@
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
+import org.hibernate.engine.loading.LoadContexts;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
@@ -21,16 +22,20 @@
public interface PersistenceContext {
public boolean isStateless();
-
+
/**
- * Get the session
+ * Get the session to which this persistence context is bound.
+ *
+ * @return The session.
*/
public SessionImplementor getSession();
-
+
/**
- * Get the context for collection loading
+ * Retrieve this persistence context's managed load context.
+ *
+ * @return The load context
*/
- public CollectionLoadContext getCollectionLoadContext();
+ public LoadContexts getLoadContexts();
/**
* Add a collection which has no owner loaded
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/StatefulPersistenceContext.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/StatefulPersistenceContext.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/StatefulPersistenceContext.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -24,6 +24,7 @@
import org.hibernate.NonUniqueObjectException;
import org.hibernate.PersistentObjectException;
import org.hibernate.TransientObjectException;
+import org.hibernate.engine.loading.LoadContexts;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.persister.collection.CollectionPersister;
@@ -101,7 +102,7 @@
private boolean hasNonReadOnlyEntities = false;
- private CollectionLoadContext collectionLoadContext;
+ private LoadContexts loadContexts;
private BatchFetchQueue batchFetchQueue;
@@ -142,11 +143,11 @@
return session;
}
- public CollectionLoadContext getCollectionLoadContext() {
- if (collectionLoadContext==null) {
- collectionLoadContext = new CollectionLoadContext(this);
+ public LoadContexts getLoadContexts() {
+ if ( loadContexts == null ) {
+ loadContexts = new LoadContexts( this );
}
- return collectionLoadContext;
+ return loadContexts;
}
public void addUnownedCollection(CollectionKey key, PersistentCollection collection) {
Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/CollectionLoadContext.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -0,0 +1,332 @@
+package org.hibernate.engine.loading;
+
+import java.sql.ResultSet;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Comparator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.EntityMode;
+import org.hibernate.CacheMode;
+import org.hibernate.cache.entry.CollectionCacheEntry;
+import org.hibernate.cache.CacheKey;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.engine.CollectionKey;
+import org.hibernate.engine.Status;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.engine.CollectionEntry;
+import org.hibernate.engine.SessionFactoryImplementor;
+
+/**
+ * Represents state associated with the processing of a given {@link ResultSet}
+ * in regards to loading collections.
+ * <p/>
+ * Another implementation option to consider is to not expose {@link ResultSet}s
+ * directly (in the JDBC redesign) but to always "wrap" them and apply a
+ * [series of] context[s] to that wrapper.
+ *
+ * @author Steve Ebersole
+ */
+public class CollectionLoadContext {
+ private static final Log log = LogFactory.getLog( CollectionLoadContext.class );
+
+ private final LoadContexts loadContexts;
+ private final ResultSet resultSet;
+ private final Map loadingCollections = new HashMap( 8 );
+
+ /**
+ * Creates a collection load context for the given result set.
+ *
+ * @param loadContexts Callback to other collection load contexts.
+ * @param resultSet The result set this is "wrapping".
+ */
+ public CollectionLoadContext(LoadContexts loadContexts, ResultSet resultSet) {
+ this.loadContexts = loadContexts;
+ this.resultSet = resultSet;
+ }
+
+ public ResultSet getResultSet() {
+ return resultSet;
+ }
+
+ public LoadContexts getLoadContext() {
+ return loadContexts;
+ }
+
+ /**
+ * Retrieve the collection that is being loaded as part of processing this
+ * result set.
+ * <p/>
+ * Basically, there are two valid return values from this method:<ul>
+ * <li>an instance of {@link PersistentCollection} which indicates to
+ * continue loading the result set row data into that returned collection
+ * instance; this may be either an instance already associated and in the
+ * midst of being loaded, or a newly instantiated instance as a matching
+ * associated collection was not found.</li>
+ * <li><i>null</i> indicates to ignore the corresponding result set row
+ * data relating to the requested collection; this indicates that either
+ * the collection was found to already be associated with the persistence
+ * context in a fully loaded state, or it was found in a loading state
+ * associated with another result set processing context.</li>
+ * </ul>
+ *
+ * @param persister The persister for the collection being requested.
+ * @param key The key of the collection being requested.
+ *
+ * @return The loading collection (see discussion above).
+ */
+ public PersistentCollection getLoadingCollection(final CollectionPersister persister, final Serializable key) {
+ final EntityMode em = loadContexts.getPersistenceContext().getSession().getEntityMode();
+ final CollectionKey collectionKey = new CollectionKey( persister, key, em );
+ if ( log.isTraceEnabled() ) {
+ log.trace( "starting attempt to find loading collection [" + MessageHelper.collectionInfoString( persister.getRole(), key ) + "]" );
+ }
+ final LoadingCollectionEntry loadingCollectionEntry = locateLoadingCollectionEntry( collectionKey );
+ if ( loadingCollectionEntry == null ) {
+ // look for existing collection as part of the persistence context
+ PersistentCollection collection = loadContexts.getPersistenceContext().getCollection( collectionKey );
+ if ( collection != null ) {
+ if ( collection.wasInitialized() ) {
+ log.trace( "collection already initialized; ignoring" );
+ return null; // ignore this row of results! Note the early exit
+ }
+ else {
+ // initialize this collection
+ log.trace( "collection not yet initialized; initializing" );
+ }
+ }
+ else {
+ Object owner = loadContexts.getPersistenceContext().getCollectionOwner( key, persister );
+ final boolean newlySavedEntity = owner != null
+ && loadContexts.getPersistenceContext().getEntry( owner ).getStatus() != Status.LOADING
+ && em != EntityMode.DOM4J;
+ if ( newlySavedEntity ) {
+ // important, to account for newly saved entities in query
+ // todo : some kind of check for new status...
+ log.trace( "owning entity already loaded; ignoring" );
+ return null;
+ }
+ else {
+ // create one
+ if ( log.isTraceEnabled() ) {
+ log.trace( "instantiating new collection [key=" + key + ", rs=" + resultSet + "]" );
+ }
+ collection = persister.getCollectionType()
+ .instantiate( loadContexts.getPersistenceContext().getSession(), persister, key );
+ }
+ }
+ collection.beforeInitialize( persister, -1 );
+ collection.beginRead();
+ loadingCollections.put( collectionKey, new LoadingCollectionEntry( resultSet, persister, key, collection ) );
+ return collection;
+ }
+ else {
+ if ( loadingCollectionEntry.getResultSet() == resultSet ) {
+ log.trace( "found loading collection bound to current result set processing; reading row" );
+ return loadingCollectionEntry.getCollection();
+ }
+ else {
+ // ignore this row, the collection is in process of
+ // being loaded somewhere further "up" the stack
+ log.trace( "collection is already being initialized; ignoring row" );
+ return null;
+ }
+ }
+ }
+
+ private LoadingCollectionEntry locateLoadingCollectionEntry(CollectionKey collectionKey) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "attempting to locate loading collection entry [" + collectionKey + "]" );
+ }
+ // first try our loading collections
+ LoadingCollectionEntry loadingCollectionEntry = getLocalLoadingCollectionEntry( collectionKey );
+ if ( loadingCollectionEntry == null ) {
+ // the loading collection is not associated with our result set, so check the other
+ // result sets registered with the load context...
+ loadingCollectionEntry = loadContexts.locateLoadingCollectionEntry( collectionKey, this );
+ }
+ return loadingCollectionEntry;
+ }
+
+ LoadingCollectionEntry getLocalLoadingCollectionEntry(CollectionKey key) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "attempting to locally locate loading collection entry [key=" + key + ", rs=" + resultSet + "]" );
+ }
+ return ( LoadingCollectionEntry ) loadingCollections.get( key );
+ }
+
+ /**
+ * Finish the process of collection-loading for this bound result set. Mainly this
+ * involves cleaning up resources and notifying the collections that loading is
+ * complete.
+ *
+ * @param persister The persister for which to complete loading.
+ */
+ public void endLoadingCollections(CollectionPersister persister) {
+ SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
+
+ // in an effort to avoid concurrent-modification-exceptions (from
+ // potential recursive calls back through here as a result of the
+ // eventual call to PersistentCollection#endRead), we scan the
+ // internal loadingCollections map for matches and store those matches
+ // in a temp collection. the temp collection is then used to "drive"
+ // the #endRead processing.
+ List matches = null;
+ Iterator iter = loadingCollections.values().iterator();
+ while ( iter.hasNext() ) {
+ LoadingCollectionEntry lce = (LoadingCollectionEntry) iter.next();
+ if ( lce.getResultSet() == resultSet && lce.getPersister() == persister) {
+ if ( matches == null ) {
+ matches = new ArrayList();
+ }
+ matches.add( lce );
+ if ( lce.getCollection().getOwner() == null ) {
+ session.getPersistenceContext().addUnownedCollection(
+ new CollectionKey( persister, lce.getKey(), session.getEntityMode() ),
+ lce.getCollection()
+ );
+ }
+ if ( log.isTraceEnabled() ) {
+ log.trace( "removing collection load entry [" + lce + "]" );
+ }
+ iter.remove();
+ }
+ }
+
+ endLoadingCollections( persister, matches );
+ }
+
+ private void endLoadingCollections(CollectionPersister persister, List matchedCollectionEntries) {
+ final int count = ( matchedCollectionEntries == null ) ? 0 : matchedCollectionEntries.size();
+
+ if ( log.isDebugEnabled() ) {
+ log.debug( count + " collections were found in result set for role: " + persister.getRole() );
+ }
+
+ for ( int i = 0; i < count; i++ ) {
+ LoadingCollectionEntry lce = ( LoadingCollectionEntry ) matchedCollectionEntries.get( i );
+ endLoadingCollection( lce, persister );
+ }
+
+ if ( log.isDebugEnabled() ) {
+ log.debug( count + " collections initialized for role: " + persister.getRole() );
+ }
+ }
+
+ private void endLoadingCollection(LoadingCollectionEntry lce, CollectionPersister persister) {
+ if ( log.isTraceEnabled() ) {
+ log.debug( "ending loading collection [" + lce + "]" );
+ }
+ final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
+ final EntityMode em = session.getEntityMode();
+
+ boolean hasNoQueuedAdds = lce.getCollection().endRead(); // warning: can cause a recursive calls! (proxy initialization)
+
+ if ( persister.getCollectionType().hasHolder( em ) ) {
+ getLoadContext().getPersistenceContext().addCollectionHolder( lce.getCollection() );
+ }
+
+ CollectionEntry ce = getLoadContext().getPersistenceContext().getCollectionEntry( lce.getCollection() );
+ if ( ce == null ) {
+ ce = getLoadContext().getPersistenceContext().addInitializedCollection( persister, lce.getCollection(), lce.getKey() );
+ }
+ else {
+ ce.postInitialize( lce.getCollection() );
+ }
+
+ boolean addToCache = hasNoQueuedAdds && // there were no queued additions
+ persister.hasCache() && // and the role has a cache
+ session.getCacheMode().isPutEnabled() &&
+ !ce.isDoremove(); // and this is not a forced initialization during flush
+ if ( addToCache ) {
+ addCollectionToCache( lce, persister );
+ }
+
+ if ( log.isDebugEnabled() ) {
+ log.debug( "collection fully initialized: " + MessageHelper.collectionInfoString(persister, lce.getKey(), session.getFactory() ) );
+ }
+
+ if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
+ session.getFactory().getStatisticsImplementor().loadCollection( persister.getRole() );
+ }
+ }
+
+ /**
+ * Add the collection to the second-level cache
+ *
+ * @param lce The entry representing the collection to add
+ * @param persister The persister
+ */
+ private void addCollectionToCache(LoadingCollectionEntry lce, CollectionPersister persister) {
+ final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
+ final SessionFactoryImplementor factory = session.getFactory();
+
+ if ( log.isDebugEnabled() ) {
+ log.debug( "Caching collection: " + MessageHelper.collectionInfoString( persister, lce.getKey(), factory ) );
+ }
+
+ if ( !session.getEnabledFilters().isEmpty() && persister.isAffectedByEnabledFilters( session ) ) {
+ // some filters affecting the collection are enabled on the session, so do not do the put into the cache.
+ log.debug( "Refusing to add to cache due to enabled filters" );
+ // todo : add the notion of enabled filters to the CacheKey to differentiate filtered collections from non-filtered;
+ // but CacheKey is currently used for both collections and entities; would ideally need to define two seperate ones;
+ // currently this works in conjuction with the check on
+ // DefaultInitializeCollectionEventHandler.initializeCollectionFromCache() (which makes sure to not read from
+ // cache with enabled filters).
+ return; // EARLY EXIT!!!!!
+ }
+
+ final Comparator versionComparator;
+ final Object version;
+ if ( persister.isVersioned() ) {
+ versionComparator = persister.getOwnerEntityPersister().getVersionType().getComparator();
+ final Object collectionOwner = getLoadContext().getPersistenceContext().getCollectionOwner( lce.getKey(), persister );
+ version = getLoadContext().getPersistenceContext().getEntry( collectionOwner ).getVersion();
+ }
+ else {
+ version = null;
+ versionComparator = null;
+ }
+
+ CollectionCacheEntry entry = new CollectionCacheEntry( lce.getCollection(), persister );
+ CacheKey cacheKey = new CacheKey(
+ lce.getKey(),
+ persister.getKeyType(),
+ persister.getRole(),
+ session.getEntityMode(),
+ session.getFactory()
+ );
+ boolean put = persister.getCache().put(
+ cacheKey,
+ persister.getCacheEntryStructure().structure(entry),
+ session.getTimestamp(),
+ version,
+ versionComparator,
+ factory.getSettings().isMinimalPutsEnabled() && session.getCacheMode()!= CacheMode.REFRESH
+ );
+
+ if ( put && factory.getStatistics().isStatisticsEnabled() ) {
+ factory.getStatisticsImplementor().secondLevelCachePut( persister.getCache().getRegionName() );
+ }
+ }
+
+ void cleanup() {
+ if ( !loadingCollections.isEmpty() ) {
+ log.warn( "On CollectionLoadContext#clear, loadingCollections contained [" + loadingCollections.size() + "] entries" );
+ }
+ loadingCollections.clear();
+ }
+
+
+ public String toString() {
+ return super.toString() + "<rs=" + resultSet + ">";
+ }
+}
Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/EntityLoadContext.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/EntityLoadContext.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/EntityLoadContext.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -0,0 +1,33 @@
+package org.hibernate.engine.loading;
+
+import java.sql.ResultSet;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * {@inheritDoc}
+ *
+ * @author Steve Ebersole
+ */
+public class EntityLoadContext {
+ private static final Log log = LogFactory.getLog( EntityLoadContext.class );
+
+ private final LoadContexts loadContexts;
+ private final ResultSet resultSet;
+ private final List hydratingEntities = new ArrayList( 20 ); // todo : need map? the prob is a proper key, right?
+
+ public EntityLoadContext(LoadContexts loadContexts, ResultSet resultSet) {
+ this.loadContexts = loadContexts;
+ this.resultSet = resultSet;
+ }
+
+ void cleanup() {
+ if ( !hydratingEntities.isEmpty() ) {
+ log.warn( "On CollectionLoadContext#clear, hydratingEntities contained [" + hydratingEntities.size() + "] entries" );
+ }
+ hydratingEntities.clear();
+ }
+}
Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadContexts.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadContexts.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadContexts.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -0,0 +1,184 @@
+package org.hibernate.engine.loading;
+
+import java.sql.ResultSet;
+import java.util.Map;
+import java.util.Iterator;
+import java.io.Serializable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.hibernate.util.IdentityMap;
+import org.hibernate.engine.PersistenceContext;
+import org.hibernate.engine.CollectionKey;
+import org.hibernate.engine.SessionImplementor;
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.pretty.MessageHelper;
+import org.hibernate.EntityMode;
+
+/**
+ * Maps {@link ResultSet result-sets} to specific contextual data
+ * related to processing that {@link ResultSet result-sets}.
+ * <p/>
+ * Implementation note: internally an {@link IdentityMap} is used to maintain
+ * the mappings; {@link IdentityMap} was chosen because I'd rather not be
+ * dependent upon potentially bad {@link ResultSet#equals} and {ResultSet#hashCode}
+ * implementations.
+ * <p/>
+ * Considering the JDBC-redesign work, would further like this contextual info
+ * not mapped seperately, but available based on the result set being processed.
+ * This would also allow maintaining a single mapping as we could reliably get
+ * notification of the result-set closing...
+ *
+ * @author Steve Ebersole
+ */
+public class LoadContexts {
+ private static final Log log = LogFactory.getLog( LoadContexts.class );
+
+ private final PersistenceContext persistenceContext;
+ private Map collectionLoadContexts;
+ private Map entityLoadContexts;
+
+ /**
+ * Creates and binds this to the given persistence context.
+ *
+ * @param persistenceContext The persistence context to which this
+ * will be bound.
+ */
+ public LoadContexts(PersistenceContext persistenceContext) {
+ this.persistenceContext = persistenceContext;
+ }
+
+ /**
+ * Retrieves the persistence context to which this is bound.
+ *
+ * @return The persistence context to which this is bound.
+ */
+ public PersistenceContext getPersistenceContext() {
+ return persistenceContext;
+ }
+
+ /**
+ * Get the {@link CollectionLoadContext} associated with the given
+ * {@link ResultSet}, creating one if needed.
+ *
+ * @param resultSet The result set for which to retrieve the context.
+ * @return The processing context.
+ */
+ public CollectionLoadContext getCollectionLoadContext(ResultSet resultSet) {
+ CollectionLoadContext context = null;
+ if ( collectionLoadContexts == null ) {
+ collectionLoadContexts = IdentityMap.instantiate( 8 );
+ }
+ else {
+ context = ( CollectionLoadContext ) collectionLoadContexts.get( resultSet );
+ }
+ if ( context == null ) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "constructing collection load context for result set [" + resultSet + "]" );
+ }
+ context = new CollectionLoadContext( this, resultSet );
+ collectionLoadContexts.put( resultSet, context );
+ }
+ return context;
+ }
+
+ /**
+ * Attempt to locate the loading collection given the owner's key. The lookup here
+ * occurs against all result-set contexts...
+ *
+ * @param persister The collection persister
+ * @param ownerKey The owner key
+ * @return The loading collection, or null if not found.
+ */
+ public PersistentCollection locateLoadingCollection(CollectionPersister persister, Serializable ownerKey) {
+ LoadingCollectionEntry lce = locateLoadingCollectionEntry( new CollectionKey( persister, ownerKey, getEntityMode() ), null ); // note: null because here we are interested in all contexts...
+ if ( lce != null ) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "returning loading collection:" + MessageHelper.collectionInfoString( persister, ownerKey, getSession().getFactory() ) );
+ }
+ return lce.getCollection();
+ }
+ else {
+ // todo : should really move this log statement to CollectionType, where this is used from...
+ if ( log.isTraceEnabled() ) {
+ log.trace( "creating collection wrapper:" + MessageHelper.collectionInfoString( persister, ownerKey, getSession().getFactory() ) );
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Locate the LoadingCollectionEntry within *any* of the tracked
+ * {@link CollectionLoadContext}s.
+ * <p/>
+ * Implementation note: package protected, as this is meant solely for use
+ * by {@link CollectionLoadContext} to be able to locate collections
+ * being loaded by other {@link CollectionLoadContext}s/{@link ResultSet}s.
+ *
+ * @param key The collection key.
+ * @param caller The collection load context making this call (for performance optimization)
+ * @return The located entry; or null.
+ */
+ LoadingCollectionEntry locateLoadingCollectionEntry(CollectionKey key, CollectionLoadContext caller) {
+ if ( collectionLoadContexts == null ) {
+ return null;
+ }
+ if ( log.isTraceEnabled() ) {
+ log.trace( "attempting to locate loading collection entry [" + key + "] in any result-set context" );
+ }
+ LoadingCollectionEntry rtn = null;
+ Iterator itr = collectionLoadContexts.values().iterator();
+ while ( itr.hasNext() ) {
+ final CollectionLoadContext collectionLoadContext = ( CollectionLoadContext ) itr.next();
+ if ( collectionLoadContext == caller ) {
+ continue;
+ }
+ rtn = collectionLoadContext.getLocalLoadingCollectionEntry( key );
+ if ( rtn != null ) {
+ if ( log.isTraceEnabled() ) {
+ log.trace( "collection [" + key + "] located in load context [" + collectionLoadContext + "]" );
+ }
+ break;
+ }
+ }
+ return rtn;
+ }
+
+ public EntityLoadContext getEntityLoadContext(ResultSet resultSet) {
+ EntityLoadContext context = null;
+ if ( entityLoadContexts == null ) {
+ entityLoadContexts = IdentityMap.instantiate( 8 );
+ }
+ else {
+ context = ( EntityLoadContext ) entityLoadContexts.get( resultSet );
+ }
+ if ( context == null ) {
+ context = new EntityLoadContext( this, resultSet );
+ entityLoadContexts.put( resultSet, context );
+ }
+ return context;
+ }
+
+ public void cleanup(ResultSet resultSet) {
+ if ( collectionLoadContexts != null ) {
+ CollectionLoadContext collectionLoadContext = ( CollectionLoadContext ) collectionLoadContexts.remove( resultSet );
+ collectionLoadContext.cleanup();
+ }
+ if ( entityLoadContexts != null ) {
+ EntityLoadContext entityLoadContext = ( EntityLoadContext ) entityLoadContexts.remove( resultSet );
+ entityLoadContext.cleanup();
+ }
+ }
+
+ private SessionImplementor getSession() {
+ return getPersistenceContext().getSession();
+ }
+
+ private EntityMode getEntityMode() {
+ return getSession().getEntityMode();
+ }
+
+
+}
Added: branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadingCollectionEntry.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadingCollectionEntry.java (rev 0)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/engine/loading/LoadingCollectionEntry.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -0,0 +1,51 @@
+package org.hibernate.engine.loading;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+
+import org.hibernate.collection.PersistentCollection;
+import org.hibernate.persister.collection.CollectionPersister;
+import org.hibernate.pretty.MessageHelper;
+
+/**
+ * Represents a collection currently being loaded.
+ *
+ * @author Steve Ebersole
+ */
+public class LoadingCollectionEntry {
+ private final ResultSet resultSet;
+ private final CollectionPersister persister;
+ private final Serializable key;
+ private final PersistentCollection collection;
+
+ public LoadingCollectionEntry(
+ ResultSet resultSet,
+ CollectionPersister persister,
+ Serializable key,
+ PersistentCollection collection) {
+ this.resultSet = resultSet;
+ this.persister = persister;
+ this.key = key;
+ this.collection = collection;
+ }
+
+ public ResultSet getResultSet() {
+ return resultSet;
+ }
+
+ public CollectionPersister getPersister() {
+ return persister;
+ }
+
+ public Serializable getKey() {
+ return key;
+ }
+
+ public PersistentCollection getCollection() {
+ return collection;
+ }
+
+ public String toString() {
+ return getClass().getName() + "<rs=" + resultSet + ", coll=" + MessageHelper.collectionInfoString( persister.getRole(), key ) + ">@" + Integer.toHexString( hashCode() );
+ }
+}
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/Loader.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/Loader.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/loader/Loader.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -89,18 +89,24 @@
/**
* The SQL query string to be called; implemented by all subclasses
+ *
+ * @return The sql command this loader should use to get its {@link ResultSet}.
*/
protected abstract String getSQLString();
/**
* An array of persisters of entity classes contained in each row of results;
* implemented by all subclasses
+ *
+ * @return The entity persisters.
*/
protected abstract Loadable[] getEntityPersisters();
-
+
/**
* An array indicating whether the entities have eager property fetching
- * enabled
+ * enabled.
+ *
+ * @return Eager property fetching indicators.
*/
protected boolean[] getEntityEagerPropertyFetches() {
return null;
@@ -108,15 +114,21 @@
/**
* An array of indexes of the entity that owns a one-to-one association
- * to the entity at the given index (-1 if there is no "owner")
+ * to the entity at the given index (-1 if there is no "owner"). The
+ * indexes contained here are relative to the result of
+ * {@link #getEntityPersisters}.
+ *
+ * @return The owner indicators (see discussion above).
*/
protected int[] getOwners() {
return null;
}
/**
- * An array of unique key property names by which the corresponding
- * entities are referenced by other entities in the result set
+ * An array of the owner types corresponding to the {@link #getOwners()}
+ * returns. Indices indicating no owner would be null here.
+ *
+ * @return The types for the owners.
*/
protected EntityType[] getOwnerAssociationTypes() {
return null;
@@ -858,13 +870,14 @@
}
private void endCollectionLoad(
- final Object resultSetId,
- final SessionImplementor session,
- final CollectionPersister collectionPersister
- ) {
+ final Object resultSetId,
+ final SessionImplementor session,
+ final CollectionPersister collectionPersister) {
//this is a query and we are loading multiple instances of the same collection role
- session.getPersistenceContext().getCollectionLoadContext()
- .endLoadingCollections( collectionPersister, resultSetId, session );
+ session.getPersistenceContext()
+ .getLoadContexts()
+ .getCollectionLoadContext( ( ResultSet ) resultSetId )
+ .endLoadingCollections( collectionPersister );
}
protected List getResultList(List results, ResultTransformer resultTransformer) throws QueryException {
@@ -987,8 +1000,9 @@
}
}
- PersistentCollection rowCollection = persistenceContext.getCollectionLoadContext()
- .getLoadingCollection( persister, collectionRowKey, rs, session.getEntityMode() );
+ PersistentCollection rowCollection = persistenceContext.getLoadContexts()
+ .getCollectionLoadContext( rs )
+ .getLoadingCollection( persister, collectionRowKey );
if ( rowCollection != null ) {
rowCollection.readFrom( rs, persister, descriptor, owner );
@@ -1007,9 +1021,9 @@
);
}
- persistenceContext.getCollectionLoadContext()
- .getLoadingCollection( persister, optionalKey, rs, session.getEntityMode() ); //handle empty collection
-
+ persistenceContext.getLoadContexts()
+ .getCollectionLoadContext( rs )
+ .getLoadingCollection( persister, optionalKey ); // handle empty collection
}
// else no collection element, but also no owner
@@ -1024,7 +1038,7 @@
private void handleEmptyCollections(
final Serializable[] keys,
final Object resultSetId,
- final SessionImplementor session) throws HibernateException {
+ final SessionImplementor session) {
if ( keys != null ) {
// this is a collection initializer, so we must create a collection
@@ -1042,18 +1056,13 @@
MessageHelper.collectionInfoString( collectionPersisters[j], keys[i], getFactory() )
);
}
-
+
session.getPersistenceContext()
- .getCollectionLoadContext()
- .getLoadingCollection(
- collectionPersisters[j],
- keys[i],
- resultSetId,
- session.getEntityMode()
- );
+ .getLoadContexts()
+ .getCollectionLoadContext( ( ResultSet ) resultSetId )
+ .getLoadingCollection( collectionPersisters[j], keys[i] );
}
}
-
}
// else this is not a collection initializer (and empty collections will
Modified: branches/Branch_3_2/Hibernate3/src/org/hibernate/type/CollectionType.java
===================================================================
--- branches/Branch_3_2/Hibernate3/src/org/hibernate/type/CollectionType.java 2007-03-19 19:48:21 UTC (rev 11300)
+++ branches/Branch_3_2/Hibernate3/src/org/hibernate/type/CollectionType.java 2007-03-19 20:43:46 UTC (rev 11301)
@@ -101,9 +101,13 @@
/**
* Instantiate an uninitialized collection wrapper or holder. Callers MUST add the holder to the
* persistence context!
+ *
+ * @param session The session from which the request is originating.
+ * @param persister The underlying collection persister (metadata)
+ * @param key The owner key.
+ * @return The instantiated collection.
*/
- public abstract PersistentCollection instantiate(SessionImplementor session,
- CollectionPersister persister, Serializable key) throws HibernateException;
+ public abstract PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister, Serializable key);
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
@@ -145,8 +149,7 @@
}
}
- protected String renderLoggableString(Object value, SessionFactoryImplementor factory)
- throws HibernateException {
+ protected String renderLoggableString(Object value, SessionFactoryImplementor factory) {
if ( Element.class.isInstance( value ) ) {
// for DOM4J "collections" only
// TODO: it would be better if this was done at the higher level by Printer
@@ -174,6 +177,10 @@
/**
* Get an iterator over the element set of the collection, which may not yet be wrapped
+ *
+ * @param collection The collection to be iterated
+ * @param session The session from which the request is originating.
+ * @return The iterator.
*/
public Iterator getElementsIterator(Object collection, SessionImplementor session) {
if ( session.getEntityMode()==EntityMode.DOM4J ) {
@@ -196,6 +203,9 @@
/**
* Get an iterator over the element set of the collection in POJO mode
+ *
+ * @param collection The collection to be iterated
+ * @return The iterator.
*/
protected Iterator getElementsIterator(Object collection) {
return ( (Collection) collection ).iterator();
@@ -241,16 +251,25 @@
/**
* Is the owning entity versioned?
+ *
+ * @param session The session from which the request is originating.
+ * @return True if the collection owner is versioned; false otherwise.
+ * @throws MappingException Indicates the underlying persister could not be located.
*/
private boolean isOwnerVersioned(SessionImplementor session) throws MappingException {
- return getPersister( session )
- .getOwnerEntityPersister()
- .isVersioned();
+ return getPersister( session ).getOwnerEntityPersister().isVersioned();
}
- private CollectionPersister getPersister(SessionImplementor session) {
- return session.getFactory()
- .getCollectionPersister( role );
+ /**
+ * Get our underlying collection persister (using the session to access the
+ * factory).
+ *
+ * @param session The session from which the request is originating.
+ * @return The underlying collection persister
+ * @throws org.hibernate.MappingException Indicates the underlying persister could not be located.
+ */
+ private CollectionPersister getPersister(SessionImplementor session) throws MappingException {
+ return session.getFactory().getCollectionPersister( role );
}
public boolean isDirty(Object old, Object current, SessionImplementor session)
@@ -269,9 +288,14 @@
throws HibernateException {
return isDirty(old, current, session);
}
+
/**
- * Wrap the naked collection instance in a wrapper, or instantiate a holder. Callers MUST add
- * the holder to the persistence context!
+ * Wrap the naked collection instance in a wrapper, or instantiate a
+ * holder. Callers <b>MUST</b> add the holder to the persistence context!
+ *
+ * @param session The session from which the request is originating.
+ * @param collection The bare collection to be wrapped.
+ * @return The wrapped collection.
*/
public abstract PersistentCollection wrap(SessionImplementor session, Object collection);
@@ -290,6 +314,10 @@
/**
* Get the key value from the owning entity instance, usually the identifier, but might be some
* other unique key, in the case of property-ref
+ *
+ * @param owner The collection owner
+ * @param session The session from which the request is originating.
+ * @return The collection owner's key
*/
public Serializable getKeyOfOwner(Object owner, SessionImplementor session) {
@@ -518,9 +546,13 @@
/**
* instantiate a collection wrapper (called when loading an object)
+ *
+ * @param key The collection owner key
+ * @param session The session from which the request is originating.
+ * @param owner The collection owner
+ * @return The collection
*/
- public Object getCollection(Serializable key, SessionImplementor session, Object owner)
- throws HibernateException {
+ public Object getCollection(Serializable key, SessionImplementor session, Object owner) {
CollectionPersister persister = getPersister( session );
final PersistenceContext persistenceContext = session.getPersistenceContext();
@@ -529,25 +561,19 @@
if (entityMode==EntityMode.DOM4J && !isEmbeddedInXML) {
return UNFETCHED_COLLECTION;
}
-
+
// check if collection is currently being loaded
- PersistentCollection collection = persistenceContext
- .getCollectionLoadContext()
- .getLoadingCollection( persister, key, entityMode );
-
+ PersistentCollection collection = persistenceContext.getLoadContexts().locateLoadingCollection( persister, key );
if ( collection == null ) {
-
// check if it is already completely loaded, but unowned
collection = persistenceContext.useUnownedCollection( new CollectionKey(persister, key, entityMode) );
-
- if (collection==null) {
-
+ if ( collection == null ) {
// create a new collection wrapper, to be initialized later
collection = instantiate( session, persister, key );
- collection.setOwner(owner);
-
+ collection.setOwner( owner );
+
persistenceContext.addUninitializedCollection( persister, collection, key );
-
+
// some collections are not lazy:
if ( initializeImmediately( entityMode ) ) {
session.initializeCollection( collection, false );
@@ -559,13 +585,9 @@
if ( hasHolder( entityMode ) ) {
session.getPersistenceContext().addCollectionHolder( collection );
}
-
}
-
}
-
- collection.setOwner(owner);
-
+ collection.setOwner( owner );
return collection.getValue();
}
More information about the hibernate-commits
mailing list