use of org.hibernate.engine.spi.CollectionEntry in project hibernate-orm by hibernate.
the class UnversionedCascadeDereferencedCollectionTest method testGetAndNullifyCollection.
@Test
@TestForIssue(jiraKey = "HHH-9777")
public void testGetAndNullifyCollection() {
Session s = openSession();
s.getTransaction().begin();
UnversionedCascadeOne one = new UnversionedCascadeOne();
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 = UnversionedCascadeOne.class.getName() + ".manies";
s = openSession();
s.getTransaction().begin();
one = (UnversionedCascadeOne) s.get(UnversionedCascadeOne.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 ceManies = getCollectionEntry(s, maniesEEOneStateOrig);
assertNotNull(ceManies);
assertEquals(role, ceManies.getRole());
assertSame(sessionFactory().getCollectionPersister(role), ceManies.getLoadedPersister());
assertEquals(one.getId(), ceManies.getKey());
// nullify collection
one.setManies(null);
s.flush();
// Ensure the same EntityEntry is being used.
assertSame(eeOne, getEntityEntry(s, one));
// Ensure one.getManies() is still null.
assertNull(one.getManies());
// 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(ceManies.getRole());
assertNull(ceManies.getLoadedPersister());
assertNull(ceManies.getKey());
// Ensure the PersistentCollection (that was previously returned by eeOne.getLoadedState())
// has key and role set to null.
assertNull(maniesEEOneStateOrig.getKey());
assertNull(maniesEEOneStateOrig.getRole());
// Ensure eeOne.getLoadedState() returns null for collection afterQuery flush.
assertNull(eeOne.getLoadedValue("manies"));
// Ensure the session in maniesEEOneStateOrig has been unset.
assertNull(maniesEEOneStateOrig.getSession());
s.getTransaction().commit();
s.close();
}
use of org.hibernate.engine.spi.CollectionEntry in project hibernate-orm by hibernate.
the class MultipleSessionCollectionWarningTest method testUnsetSessionCannotOverwriteConnectedSesssionFlushed.
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testUnsetSessionCannotOverwriteConnectedSesssionFlushed() {
Parent p = new Parent();
Child c = new Child();
p.children.add(c);
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate(p);
// flush the session so that p.children will contain its role
s1.flush();
// The collection is "connected" to s1 because it contains the CollectionEntry
CollectionEntry ce = ((SessionImplementor) s1).getPersistenceContext().getCollectionEntry((PersistentCollection) p.children);
assertNotNull(ce);
// the collection session should be s1
assertSame(s1, ((AbstractPersistentCollection) p.children).getSession());
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages("HHH000471:");
assertFalse(triggerable.wasTriggered());
// The following should trigger warning because we're unsetting a different session
// We should not do this in practice; it is done here only to force the warning.
// The collection role and key should be included in the message (no way to test that other than inspection).
assertFalse(((PersistentCollection) p.children).unsetSession((SessionImplementor) s2));
assertTrue(triggerable.wasTriggered());
// collection's session should still be s1
assertSame(s1, ((AbstractPersistentCollection) p.children).getSession());
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
use of org.hibernate.engine.spi.CollectionEntry in project hibernate-orm by hibernate.
the class MultipleSessionCollectionWarningTest method testUnsetSessionCannotOverwriteNonConnectedSesssion.
@Test
@TestForIssue(jiraKey = "HHH-9518")
public void testUnsetSessionCannotOverwriteNonConnectedSesssion() {
Parent p = new Parent();
Child c = new Child();
p.children.add(c);
Session s1 = openSession();
s1.getTransaction().begin();
s1.saveOrUpdate(p);
// Now remove the collection from the PersistenceContext without unsetting its session
// This should never be done in practice; it is done here only to test that the warning
// gets logged. s1 will not function properly so the transaction will ultimately need
// to be rolled-back.
CollectionEntry ce = (CollectionEntry) ((SessionImplementor) s1).getPersistenceContext().getCollectionEntries().remove(p.children);
assertNotNull(ce);
// the collection session should still be s1; the collection is no longer "connected" because its
// CollectionEntry has been removed.
assertSame(s1, ((AbstractPersistentCollection) p.children).getSession());
Session s2 = openSession();
s2.getTransaction().begin();
Triggerable triggerable = logInspection.watchForLogMessages("HHH000471:");
assertFalse(triggerable.wasTriggered());
// The following should trigger warning because we're unsetting a different session.
// We should not do this in practice; it is done here only to force the warning.
// Since s1 was not flushed, the collection role will not be known (no way to test that).
assertFalse(((PersistentCollection) p.children).unsetSession((SessionImplementor) s2));
assertTrue(triggerable.wasTriggered());
// collection's session should still be s1
assertSame(s1, ((AbstractPersistentCollection) p.children).getSession());
s2.getTransaction().rollback();
s2.close();
s1.getTransaction().rollback();
s1.close();
}
use of org.hibernate.engine.spi.CollectionEntry 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);
}
}
}
use of org.hibernate.engine.spi.CollectionEntry in project hibernate-orm by hibernate.
the class CollectionLoadContext method endLoadingCollection.
private void endLoadingCollection(LoadingCollectionEntry lce, CollectionPersister persister) {
LOG.tracev("Ending loading collection [{0}]", lce);
final SharedSessionContractImplementor session = getLoadContext().getPersistenceContext().getSession();
// warning: can cause a recursive calls! (proxy initialization)
final boolean hasNoQueuedAdds = lce.getCollection().endRead();
if (persister.getCollectionType().hasHolder()) {
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());
// if (ce.getLoadedPersister().getBatchSize() > 1) { // not the best place for doing this, moved into ce.postInitialize
// getLoadContext().getPersistenceContext().getBatchFetchQueue().removeBatchLoadableCollection(ce);
// }
}
// add to cache if:
boolean addToCache = // there were no queued additions
hasNoQueuedAdds && // and the role has a cache
persister.hasCache() && // and this is not a forced initialization during flush
session.getCacheMode().isPutEnabled() && !ce.isDoremove();
if (addToCache) {
addCollectionToCache(lce, persister);
}
if (LOG.isDebugEnabled()) {
LOG.debugf("Collection fully initialized: %s", MessageHelper.collectionInfoString(persister, lce.getCollection(), lce.getKey(), session));
}
if (session.getFactory().getStatistics().isStatisticsEnabled()) {
session.getFactory().getStatistics().loadCollection(persister.getRole());
}
}
Aggregations