Search in sources :

Example 41 with PersistentCollection

use of org.hibernate.collection.spi.PersistentCollection in project hibernate-orm by hibernate.

the class Cascade method cascadeCollectionElements.

/**
	 * Cascade to the collection elements
	 */
private static void cascadeCollectionElements(final CascadingAction action, final CascadePoint cascadePoint, final EventSource eventSource, final int componentPathStackDepth, final Object parent, final Object child, final CollectionType collectionType, final CascadeStyle style, final Type elemType, final Object anything, final boolean isCascadeDeleteEnabled) throws HibernateException {
    final boolean reallyDoCascade = style.reallyDoCascade(action) && child != CollectionType.UNFETCHED_COLLECTION;
    if (reallyDoCascade) {
        final boolean traceEnabled = LOG.isTraceEnabled();
        if (traceEnabled) {
            LOG.tracev("Cascade {0} for collection: {1}", action, collectionType.getRole());
        }
        final Iterator itr = action.getCascadableChildrenIterator(eventSource, collectionType, child);
        while (itr.hasNext()) {
            cascadeProperty(action, cascadePoint, eventSource, componentPathStackDepth, parent, itr.next(), elemType, style, null, anything, isCascadeDeleteEnabled);
        }
        if (traceEnabled) {
            LOG.tracev("Done cascade {0} for collection: {1}", action, collectionType.getRole());
        }
    }
    final boolean deleteOrphans = style.hasOrphanDelete() && action.deleteOrphans() && elemType.isEntityType() && // a newly instantiated collection can't have orphans
    child instanceof PersistentCollection;
    if (deleteOrphans) {
        final boolean traceEnabled = LOG.isTraceEnabled();
        if (traceEnabled) {
            LOG.tracev("Deleting orphans for collection: {0}", collectionType.getRole());
        }
        // we can do the cast since orphan-delete does not apply to:
        // 1. newly instantiated collections
        // 2. arrays (we can't track orphans for detached arrays)
        final String entityName = collectionType.getAssociatedEntityName(eventSource.getFactory());
        deleteOrphans(eventSource, entityName, (PersistentCollection) child);
        if (traceEnabled) {
            LOG.tracev("Done deleting orphans for collection: {0}", collectionType.getRole());
        }
    }
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) Iterator(java.util.Iterator)

Example 42 with PersistentCollection

use of org.hibernate.collection.spi.PersistentCollection in project hibernate-orm by hibernate.

the class UnversionedNoCascadeDereferencedCollectionTest method testGetAndReplaceCollection.

@Test
@TestForIssue(jiraKey = "HHH-9777")
public void testGetAndReplaceCollection() {
    Session s = openSession();
    s.getTransaction().begin();
    UnversionedNoCascadeOne one = new UnversionedNoCascadeOne();
    assertNull(one.getManies());
    s.save(one);
    assertNull(one.getManies());
    EntityEntry eeOne = getEntityEntry(s, one);
    assertNull(eeOne.getLoadedValue("manies"));
    s.flush();
    assertNull(one.getManies());
    assertNull(eeOne.getLoadedValue("manies"));
    s.getTransaction().commit();
    s.close();
    final String role = UnversionedNoCascadeOne.class.getName() + ".manies";
    s = openSession();
    s.getTransaction().begin();
    one = (UnversionedNoCascadeOne) s.get(UnversionedNoCascadeOne.class, one.getId());
    // When returned by Session.get(), one.getManies() will return a PersistentCollection;
    // the EntityEntry loaded state should contain the same PersistentCollection.
    eeOne = getEntityEntry(s, one);
    assertNotNull(one.getManies());
    AbstractPersistentCollection maniesEEOneStateOrig = (AbstractPersistentCollection) eeOne.getLoadedValue("manies");
    assertSame(one.getManies(), maniesEEOneStateOrig);
    // Ensure maniesEEOneStateOrig has role, key, and session properly defined (even though one.manies == null)
    assertEquals(role, maniesEEOneStateOrig.getRole());
    assertEquals(one.getId(), maniesEEOneStateOrig.getKey());
    assertSame(s, maniesEEOneStateOrig.getSession());
    // Ensure there is a CollectionEntry for maniesEEOneStateOrig and that the role, persister, and key are set properly.
    CollectionEntry ceManiesOrig = getCollectionEntry(s, maniesEEOneStateOrig);
    assertNotNull(ceManiesOrig);
    assertEquals(role, ceManiesOrig.getRole());
    assertSame(sessionFactory().getCollectionPersister(role), ceManiesOrig.getLoadedPersister());
    assertEquals(one.getId(), ceManiesOrig.getKey());
    // replace collection
    one.setManies(new HashSet<Many>());
    s.flush();
    // Ensure the same EntityEntry is being used.
    assertSame(eeOne, getEntityEntry(s, one));
    // Ensure CollectionEntry for maniesEEOneStateOrig is no longer in the PersistenceContext.
    assertNull(getCollectionEntry(s, maniesEEOneStateOrig));
    // Ensure the original CollectionEntry has role, persister, and key set to null.
    assertNull(ceManiesOrig.getRole());
    assertNull(ceManiesOrig.getLoadedPersister());
    assertNull(ceManiesOrig.getKey());
    // Ensure the PersistentCollection (that was previously returned by eeOne.getLoadedState())
    // has key and role set to null.
    assertNull(maniesEEOneStateOrig.getKey());
    assertNull(maniesEEOneStateOrig.getRole());
    // one.getManies() should be "wrapped" by a PersistentCollection now; role, key, and session should be set properly.
    assertTrue(PersistentCollection.class.isInstance(one.getManies()));
    assertEquals(role, ((PersistentCollection) one.getManies()).getRole());
    assertEquals(one.getId(), ((PersistentCollection) one.getManies()).getKey());
    assertSame(s, ((AbstractPersistentCollection) one.getManies()).getSession());
    // Ensure eeOne.getLoadedState() contains the new collection.
    assertSame(one.getManies(), eeOne.getLoadedValue("manies"));
    // Ensure there is a new CollectionEntry for the new collection and that role, persister, and key are set properly.
    CollectionEntry ceManiesAfterReplace = getCollectionEntry(s, (PersistentCollection) one.getManies());
    assertNotNull(ceManiesAfterReplace);
    assertEquals(role, ceManiesAfterReplace.getRole());
    assertSame(sessionFactory().getCollectionPersister(role), ceManiesAfterReplace.getLoadedPersister());
    assertEquals(one.getId(), ceManiesAfterReplace.getKey());
    // Ensure the session in maniesEEOneStateOrig has been unset.
    assertNull(maniesEEOneStateOrig.getSession());
    s.getTransaction().commit();
    s.close();
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) EntityEntry(org.hibernate.engine.spi.EntityEntry) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) CollectionEntry(org.hibernate.engine.spi.CollectionEntry) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 43 with PersistentCollection

use of org.hibernate.collection.spi.PersistentCollection in project hibernate-orm by hibernate.

the class VersionedCascadeDereferencedCollectionTest method testGetAndReplaceCollection.

@Test
@TestForIssue(jiraKey = "HHH-9777")
public void testGetAndReplaceCollection() {
    Session s = openSession();
    s.getTransaction().begin();
    VersionedCascadeOne one = new VersionedCascadeOne();
    assertNull(one.getManies());
    s.save(one);
    assertNull(one.getManies());
    EntityEntry eeOne = getEntityEntry(s, one);
    assertNull(eeOne.getLoadedValue("manies"));
    s.flush();
    assertNull(one.getManies());
    assertNull(eeOne.getLoadedValue("manies"));
    s.getTransaction().commit();
    s.close();
    final String role = VersionedCascadeOne.class.getName() + ".manies";
    s = openSession();
    s.getTransaction().begin();
    one = (VersionedCascadeOne) s.get(VersionedCascadeOne.class, one.getId());
    // When returned by Session.get(), one.getManies() will return a PersistentCollection;
    // the EntityEntry loaded state should contain the same PersistentCollection.
    eeOne = getEntityEntry(s, one);
    assertNotNull(one.getManies());
    AbstractPersistentCollection maniesEEOneStateOrig = (AbstractPersistentCollection) eeOne.getLoadedValue("manies");
    assertSame(one.getManies(), maniesEEOneStateOrig);
    // Ensure maniesEEOneStateOrig has role, key, and session properly defined (even though one.manies == null)
    assertEquals(role, maniesEEOneStateOrig.getRole());
    assertEquals(one.getId(), maniesEEOneStateOrig.getKey());
    assertSame(s, maniesEEOneStateOrig.getSession());
    // Ensure there is a CollectionEntry for maniesEEOneStateOrig and that the role, persister, and key are set properly.
    CollectionEntry ceManiesOrig = getCollectionEntry(s, maniesEEOneStateOrig);
    assertNotNull(ceManiesOrig);
    assertEquals(role, ceManiesOrig.getRole());
    assertSame(sessionFactory().getCollectionPersister(role), ceManiesOrig.getLoadedPersister());
    assertEquals(one.getId(), ceManiesOrig.getKey());
    // replace collection
    one.setManies(new HashSet<Many>());
    s.flush();
    // Ensure the same EntityEntry is being used.
    assertSame(eeOne, getEntityEntry(s, one));
    // Ensure CollectionEntry for maniesEEOneStateOrig is no longer in the PersistenceContext.
    assertNull(getCollectionEntry(s, maniesEEOneStateOrig));
    // Ensure the original CollectionEntry has role, persister, and key set to null.
    assertNull(ceManiesOrig.getRole());
    assertNull(ceManiesOrig.getLoadedPersister());
    assertNull(ceManiesOrig.getKey());
    // Ensure the PersistentCollection (that was previously returned by eeOne.getLoadedState())
    // has key and role set to null.
    assertNull(maniesEEOneStateOrig.getKey());
    assertNull(maniesEEOneStateOrig.getRole());
    // one.getManies() should be "wrapped" by a PersistentCollection now; role, key, and session should be set properly.
    assertTrue(PersistentCollection.class.isInstance(one.getManies()));
    assertEquals(role, ((PersistentCollection) one.getManies()).getRole());
    assertEquals(one.getId(), ((PersistentCollection) one.getManies()).getKey());
    assertSame(s, ((AbstractPersistentCollection) one.getManies()).getSession());
    // Ensure eeOne.getLoadedState() contains the new collection.
    assertSame(one.getManies(), eeOne.getLoadedValue("manies"));
    // Ensure there is a new CollectionEntry for the new collection and that role, persister, and key are set properly.
    CollectionEntry ceManiesAfterReplace = getCollectionEntry(s, (PersistentCollection) one.getManies());
    assertNotNull(ceManiesAfterReplace);
    assertEquals(role, ceManiesAfterReplace.getRole());
    assertSame(sessionFactory().getCollectionPersister(role), ceManiesAfterReplace.getLoadedPersister());
    assertEquals(one.getId(), ceManiesAfterReplace.getKey());
    // Ensure the session in maniesEEOneStateOrig has been unset.
    assertNull(maniesEEOneStateOrig.getSession());
    s.getTransaction().commit();
    s.close();
}
Also used : PersistentCollection(org.hibernate.collection.spi.PersistentCollection) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) EntityEntry(org.hibernate.engine.spi.EntityEntry) AbstractPersistentCollection(org.hibernate.collection.internal.AbstractPersistentCollection) CollectionEntry(org.hibernate.engine.spi.CollectionEntry) Session(org.hibernate.Session) Test(org.junit.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 44 with PersistentCollection

use of org.hibernate.collection.spi.PersistentCollection 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 45 with PersistentCollection

use of org.hibernate.collection.spi.PersistentCollection 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)

Aggregations

PersistentCollection (org.hibernate.collection.spi.PersistentCollection)53 Session (org.hibernate.Session)20 Test (org.junit.Test)20 Transaction (org.hibernate.Transaction)16 ChildWithBidirectionalManyToMany (org.hibernate.test.event.collection.association.bidirectional.manytomany.ChildWithBidirectionalManyToMany)15 Collection (java.util.Collection)13 CollectionEntry (org.hibernate.engine.spi.CollectionEntry)11 CollectionPersister (org.hibernate.persister.collection.CollectionPersister)8 AbstractPersistentCollection (org.hibernate.collection.internal.AbstractPersistentCollection)7 EntityEntry (org.hibernate.engine.spi.EntityEntry)7 Serializable (java.io.Serializable)6 CollectionKey (org.hibernate.engine.spi.CollectionKey)6 HibernateException (org.hibernate.HibernateException)5 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)5 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)5 Map (java.util.Map)4 IdentityMap (org.hibernate.internal.util.collections.IdentityMap)4 TestForIssue (org.hibernate.testing.TestForIssue)4 HashSet (java.util.HashSet)3 Iterator (java.util.Iterator)3