/** * Initialize the role of the collection. * * @param collection The collection to be updated by reachability. * @param type The type of the collection. * @param entity The owner of the collection. * @param session The session from which this request originates */ public static void processReachableCollection( PersistentCollection collection, CollectionType type, Object entity, SessionImplementor session) { collection.setOwner(entity); CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(collection); if (ce == null) { // refer to comment in StatefulPersistenceContext.addCollection() throw new HibernateException( "Found two representations of same collection: " + type.getRole()); } // The CollectionEntry.isReached() stuff is just to detect any silly users // who set up circular or shared references between/to collections. if (ce.isReached()) { // We've been here before throw new HibernateException("Found shared references to a collection: " + type.getRole()); } ce.setReached(true); SessionFactoryImplementor factory = session.getFactory(); CollectionPersister persister = factory.getCollectionPersister(type.getRole()); ce.setCurrentPersister(persister); ce.setCurrentKey( type.getKeyOfOwner(entity, session)); // TODO: better to pass the id in as an argument? if (LOG.isDebugEnabled()) { if (collection.wasInitialized()) LOG.debugf( "Collection found: %s, was: %s (initialized)", MessageHelper.collectionInfoString(persister, ce.getCurrentKey(), factory), MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), factory)); else LOG.debugf( "Collection found: %s, was: %s (uninitialized)", MessageHelper.collectionInfoString(persister, ce.getCurrentKey(), factory), MessageHelper.collectionInfoString( ce.getLoadedPersister(), ce.getLoadedKey(), factory)); } prepareCollectionForUpdate(collection, ce, factory); }
/** * process any unreferenced collections and then inspect all known collections, scheduling * creates/removes/updates */ @SuppressWarnings("unchecked") private int flushCollections( final EventSource session, final PersistenceContext persistenceContext) throws HibernateException { LOG.trace("Processing unreferenced collections"); final Map.Entry<PersistentCollection, CollectionEntry>[] entries = IdentityMap.concurrentEntries( (Map<PersistentCollection, CollectionEntry>) persistenceContext.getCollectionEntries()); final int count = entries.length; for (Map.Entry<PersistentCollection, CollectionEntry> me : entries) { CollectionEntry ce = me.getValue(); if (!ce.isReached() && !ce.isIgnore()) { Collections.processUnreachableCollection(me.getKey(), session); } } // Schedule updates to collections: LOG.trace("Scheduling collection removes/(re)creates/updates"); ActionQueue actionQueue = session.getActionQueue(); for (Map.Entry<PersistentCollection, CollectionEntry> me : IdentityMap.concurrentEntries( (Map<PersistentCollection, CollectionEntry>) persistenceContext.getCollectionEntries())) { PersistentCollection coll = me.getKey(); CollectionEntry ce = me.getValue(); if (ce.isDorecreate()) { session.getInterceptor().onCollectionRecreate(coll, ce.getCurrentKey()); actionQueue.addAction( new CollectionRecreateAction( coll, ce.getCurrentPersister(), ce.getCurrentKey(), session)); } if (ce.isDoremove()) { session.getInterceptor().onCollectionRemove(coll, ce.getLoadedKey()); actionQueue.addAction( new CollectionRemoveAction( coll, ce.getLoadedPersister(), ce.getLoadedKey(), ce.isSnapshotEmpty(coll), session)); } if (ce.isDoupdate()) { session.getInterceptor().onCollectionUpdate(coll, ce.getLoadedKey()); actionQueue.addAction( new CollectionUpdateAction( coll, ce.getLoadedPersister(), ce.getLoadedKey(), ce.isSnapshotEmpty(coll), session)); } // todo : I'm not sure the !wasInitialized part should really be part of this check if (!coll.wasInitialized() && coll.hasQueuedOperations()) { actionQueue.addAction( new QueuedOperationCollectionAction( coll, ce.getLoadedPersister(), ce.getLoadedKey(), session)); } } actionQueue.sortCollectionActions(); return count; }