Search in sources :

Example 1 with CollectionKey

use of org.hibernate.engine.spi.CollectionKey in project hibernate-orm by hibernate.

the class CollectionLoadContext method getLoadingCollection.

/**
	 * 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 org.hibernate.collection.spi.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 = persister.getOwnerEntityPersister().getEntityMetamodel().getEntityMode();
    final CollectionKey collectionKey = new CollectionKey(persister, key, em);
    if (LOG.isTraceEnabled()) {
        LOG.tracev("Starting attempt to find loading collection [{0}]", MessageHelper.collectionInfoString(persister.getRole(), key));
    }
    final LoadingCollectionEntry loadingCollectionEntry = loadContexts.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");
                // ignore this row of results! Note the early exit
                return null;
            }
            LOG.trace("Collection not yet initialized; initializing");
        } else {
            final Object owner = loadContexts.getPersistenceContext().getCollectionOwner(key, persister);
            final boolean newlySavedEntity = owner != null && loadContexts.getPersistenceContext().getEntry(owner).getStatus() != Status.LOADING;
            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;
            }
            // create one
            LOG.tracev("Instantiating new collection [key={0}, rs={1}]", key, resultSet);
            collection = persister.getCollectionType().instantiate(loadContexts.getPersistenceContext().getSession(), persister, key);
        }
        collection.beforeInitialize(persister, -1);
        collection.beginRead();
        localLoadingCollectionKeys.add(collectionKey);
        loadContexts.registerLoadingCollectionXRef(collectionKey, new LoadingCollectionEntry(resultSet, persister, key, collection));
        return collection;
    }
    if (loadingCollectionEntry.getResultSet() == resultSet) {
        LOG.trace("Found loading collection bound to current result set processing; reading row");
        return loadingCollectionEntry.getCollection();
    }
    // 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;
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) CollectionKey(org.hibernate.engine.spi.CollectionKey) EntityMode(org.hibernate.EntityMode)

Example 2 with CollectionKey

use of org.hibernate.engine.spi.CollectionKey in project hibernate-orm by hibernate.

the class AbstractFlushingEventListener method postFlush.

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Post-flushing section
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
	 * 1. Recreate the collection key -> collection map
	 * 2. rebuild the collection entries
	 * 3. call Interceptor.postFlush()
	 */
protected void postFlush(SessionImplementor session) throws HibernateException {
    LOG.trace("Post flush");
    final PersistenceContext persistenceContext = session.getPersistenceContext();
    persistenceContext.getCollectionsByKey().clear();
    // the database has changed now, so the subselect results need to be invalidated
    // the batch fetching queues should also be cleared - especially the collection batch fetching one
    persistenceContext.getBatchFetchQueue().clear();
    for (Map.Entry<PersistentCollection, CollectionEntry> 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, unset its session reference and remove from the session cache
            //iter.remove(); //does not work, since the entrySet is not backed by the set
            persistentCollection.unsetSession(session);
            persistenceContext.getCollectionEntries().remove(persistentCollection);
        } else {
            //otherwise recreate the mapping between the collection and its key
            CollectionKey collectionKey = new CollectionKey(collectionEntry.getLoadedPersister(), collectionEntry.getLoadedKey());
            persistenceContext.getCollectionsByKey().put(collectionKey, persistentCollection);
        }
    }
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) CollectionEntry(org.hibernate.engine.spi.CollectionEntry) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) CollectionKey(org.hibernate.engine.spi.CollectionKey) Map(java.util.Map) IdentityMap(org.hibernate.internal.util.collections.IdentityMap)

Example 3 with CollectionKey

use of org.hibernate.engine.spi.CollectionKey in project hibernate-orm by hibernate.

the class CollectionLoadContext method endLoadingCollections.

/**
	 * 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) {
    final SharedSessionContractImplementor session = getLoadContext().getPersistenceContext().getSession();
    if (!loadContexts.hasLoadingCollectionEntries() && localLoadingCollectionKeys.isEmpty()) {
        return;
    }
    // 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<LoadingCollectionEntry> matches = null;
    final Iterator itr = localLoadingCollectionKeys.iterator();
    while (itr.hasNext()) {
        final CollectionKey collectionKey = (CollectionKey) itr.next();
        final LoadingCollectionEntry lce = loadContexts.locateLoadingCollectionEntry(collectionKey);
        if (lce == null) {
            LOG.loadingCollectionKeyNotFound(collectionKey);
        } else 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(), persister.getOwnerEntityPersister().getEntityMetamodel().getEntityMode()), lce.getCollection());
            }
            LOG.tracev("Removing collection load entry [{0}]", lce);
            // todo : i'd much rather have this done from #endLoadingCollection(CollectionPersister,LoadingCollectionEntry)...
            loadContexts.unregisterLoadingCollectionXRef(collectionKey);
            itr.remove();
        }
    }
    endLoadingCollections(persister, matches);
    if (localLoadingCollectionKeys.isEmpty()) {
        // todo : hack!!!
        // NOTE : here we cleanup the load context when we have no more local
        // LCE entries.  This "works" for the time being because really
        // only the collection load contexts are implemented.  Long term,
        // this cleanup should become part of the "close result set"
        // processing from the (sandbox/jdbc) jdbc-container code.
        loadContexts.cleanup(resultSet);
    }
}
Also used : Iterator(java.util.Iterator) ArrayList(java.util.ArrayList) SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) CollectionKey(org.hibernate.engine.spi.CollectionKey)

Example 4 with CollectionKey

use of org.hibernate.engine.spi.CollectionKey in project hibernate-orm by hibernate.

the class AbstractEntityPersister method initializeLazyProperty.

public Object initializeLazyProperty(String fieldName, Object entity, SharedSessionContractImplementor session) {
    final EntityEntry entry = session.getPersistenceContext().getEntry(entity);
    final InterceptorImplementor interceptor = ((PersistentAttributeInterceptable) entity).$$_hibernate_getInterceptor();
    assert interceptor != null : "Expecting bytecode interceptor to be non-null";
    if (hasCollections()) {
        final Type type = getPropertyType(fieldName);
        if (type.isCollectionType()) {
            // we have a condition where a collection attribute is being access via enhancement:
            // 		we can circumvent all the rest and just return the PersistentCollection
            final CollectionType collectionType = (CollectionType) type;
            final CollectionPersister persister = factory.getMetamodel().collectionPersister(collectionType.getRole());
            // Get/create the collection, and make sure it is initialized!  This initialized part is
            // different from proxy-based scenarios where we have to create the PersistentCollection
            // reference "ahead of time" to add as a reference to the proxy.  For bytecode solutions
            // we are not creating the PersistentCollection ahead of time, but instead we are creating
            // it on first request through the enhanced entity.
            // see if there is already a collection instance associated with the session
            // 		NOTE : can this ever happen?
            final Serializable key = getCollectionKey(persister, entity, entry, session);
            PersistentCollection collection = session.getPersistenceContext().getCollection(new CollectionKey(persister, key));
            if (collection == null) {
                collection = collectionType.instantiate(session, persister, key);
                collection.setOwner(entity);
                session.getPersistenceContext().addUninitializedCollection(persister, collection, key);
            }
            // HHH-11161 Initialize, if the collection is not extra lazy
            if (!persister.isExtraLazy()) {
                session.initializeCollection(collection, false);
            }
            interceptor.attributeInitialized(fieldName);
            if (collectionType.isArrayType()) {
                session.getPersistenceContext().addCollectionHolder(collection);
            }
            // update the "state" of the entity's EntityEntry to over-write UNFETCHED_PROPERTY reference
            // for the collection to the just loaded collection
            final EntityEntry ownerEntry = session.getPersistenceContext().getEntry(entity);
            if (ownerEntry == null) {
                // not good
                throw new AssertionFailure("Could not locate EntityEntry for the collection owner in the PersistenceContext");
            }
            ownerEntry.overwriteLoadedStateCollectionValue(fieldName, collection);
            // EARLY EXIT!!!
            return collection;
        }
    }
    final Serializable id = session.getContextEntityIdentifier(entity);
    if (entry == null) {
        throw new HibernateException("entity is not associated with the session: " + id);
    }
    if (LOG.isTraceEnabled()) {
        LOG.tracev("Initializing lazy properties of: {0}, field access: {1}", MessageHelper.infoString(this, id, getFactory()), fieldName);
    }
    if (session.getCacheMode().isGetEnabled() && hasCache() && isLazyPropertiesCacheable()) {
        final EntityRegionAccessStrategy cache = getCacheAccessStrategy();
        final Object cacheKey = cache.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier());
        final Object ce = CacheHelper.fromSharedCache(session, cacheKey, cache);
        if (ce != null) {
            final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory);
            final Object initializedValue = initializeLazyPropertiesFromCache(fieldName, entity, session, entry, cacheEntry);
            interceptor.attributeInitialized(fieldName);
            // NOTE EARLY EXIT!!!
            return initializedValue;
        }
    }
    return initializeLazyPropertiesFromDatastore(fieldName, entity, session, id, entry);
}
Also used : Serializable(java.io.Serializable) AssertionFailure(org.hibernate.AssertionFailure) HibernateException(org.hibernate.HibernateException) PersistentAttributeInterceptable(org.hibernate.engine.spi.PersistentAttributeInterceptable) EntityRegionAccessStrategy(org.hibernate.cache.spi.access.EntityRegionAccessStrategy) CollectionKey(org.hibernate.engine.spi.CollectionKey) StructuredCacheEntry(org.hibernate.cache.spi.entry.StructuredCacheEntry) UnstructuredCacheEntry(org.hibernate.cache.spi.entry.UnstructuredCacheEntry) CacheEntry(org.hibernate.cache.spi.entry.CacheEntry) PersistentCollection(org.hibernate.collection.spi.PersistentCollection) EntityEntry(org.hibernate.engine.spi.EntityEntry) AssociationType(org.hibernate.type.AssociationType) JoinType(org.hibernate.sql.JoinType) CollectionType(org.hibernate.type.CollectionType) EntityType(org.hibernate.type.EntityType) ComponentType(org.hibernate.type.ComponentType) CompositeType(org.hibernate.type.CompositeType) VersionType(org.hibernate.type.VersionType) Type(org.hibernate.type.Type) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) CollectionType(org.hibernate.type.CollectionType)

Example 5 with CollectionKey

use of org.hibernate.engine.spi.CollectionKey in project hibernate-orm by hibernate.

the class CollectionType method getCollection.

/**
	 * 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, SharedSessionContractImplementor session, Object owner) {
    CollectionPersister persister = getPersister(session);
    final PersistenceContext persistenceContext = session.getPersistenceContext();
    final EntityMode entityMode = persister.getOwnerEntityPersister().getEntityMode();
    // check if collection is currently being loaded
    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) {
            collection = persistenceContext.getCollection(new CollectionKey(persister, key, entityMode));
            if (collection == null) {
                // create a new collection wrapper, to be initialized later
                collection = instantiate(session, persister, key);
                collection.setOwner(owner);
                persistenceContext.addUninitializedCollection(persister, collection, key);
                // some collections are not lazy:
                if (initializeImmediately()) {
                    session.initializeCollection(collection, false);
                } else if (!persister.isLazy()) {
                    persistenceContext.addNonLazyCollection(collection);
                }
                if (hasHolder()) {
                    session.getPersistenceContext().addCollectionHolder(collection);
                }
            }
        }
        if (LOG.isTraceEnabled()) {
            LOG.tracef("Created collection wrapper: %s", MessageHelper.collectionInfoString(persister, collection, key, session));
        }
    }
    collection.setOwner(owner);
    return collection.getValue();
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) CollectionPersister(org.hibernate.persister.collection.CollectionPersister) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) CollectionKey(org.hibernate.engine.spi.CollectionKey) EntityMode(org.hibernate.EntityMode)

Aggregations

CollectionKey (org.hibernate.engine.spi.CollectionKey)7 PersistentCollection (org.hibernate.collection.spi.PersistentCollection)6 Map (java.util.Map)2 AssertionFailure (org.hibernate.AssertionFailure)2 EntityMode (org.hibernate.EntityMode)2 CollectionEntry (org.hibernate.engine.spi.CollectionEntry)2 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)2 IdentityMap (org.hibernate.internal.util.collections.IdentityMap)2 CollectionPersister (org.hibernate.persister.collection.CollectionPersister)2 Serializable (java.io.Serializable)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 Iterator (java.util.Iterator)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1 HibernateException (org.hibernate.HibernateException)1 EntityRegionAccessStrategy (org.hibernate.cache.spi.access.EntityRegionAccessStrategy)1 CacheEntry (org.hibernate.cache.spi.entry.CacheEntry)1 StructuredCacheEntry (org.hibernate.cache.spi.entry.StructuredCacheEntry)1 UnstructuredCacheEntry (org.hibernate.cache.spi.entry.UnstructuredCacheEntry)1