private static void processDereferencedCollection( PersistentCollection coll, SessionImplementor session) { final PersistenceContext persistenceContext = session.getPersistenceContext(); CollectionEntry entry = persistenceContext.getCollectionEntry(coll); final CollectionPersister loadedPersister = entry.getLoadedPersister(); if (LOG.isDebugEnabled() && loadedPersister != null) { LOG.debugf( "Collection dereferenced: %s", MessageHelper.collectionInfoString( loadedPersister, entry.getLoadedKey(), session.getFactory())); } // do a check boolean hasOrphanDelete = loadedPersister != null && loadedPersister.hasOrphanDelete(); if (hasOrphanDelete) { Serializable ownerId = loadedPersister.getOwnerEntityPersister().getIdentifier(coll.getOwner(), session); if (ownerId == null) { // the owning entity may have been deleted and its identifier unset due to // identifier-rollback; in which case, try to look up its identifier from // the persistence context if (session.getFactory().getSettings().isIdentifierRollbackEnabled()) { EntityEntry ownerEntry = persistenceContext.getEntry(coll.getOwner()); if (ownerEntry != null) { ownerId = ownerEntry.getId(); } } if (ownerId == null) { throw new AssertionFailure( "Unable to determine collection owner identifier for orphan-delete processing"); } } EntityKey key = session.generateEntityKey(ownerId, loadedPersister.getOwnerEntityPersister()); Object owner = persistenceContext.getEntity(key); if (owner == null) { throw new AssertionFailure( "collection owner not associated with session: " + loadedPersister.getRole()); } EntityEntry e = persistenceContext.getEntry(owner); // only collections belonging to deleted entities are allowed to be dereferenced in the case // of orphan delete if (e != null && e.getStatus() != Status.DELETED && e.getStatus() != Status.GONE) { throw new HibernateException( "A collection with cascade=\"all-delete-orphan\" was no longer referenced by the owning entity instance: " + loadedPersister.getRole()); } } // do the work entry.setCurrentPersister(null); entry.setCurrentKey(null); prepareCollectionForUpdate(coll, entry, session.getFactory()); }
/** * Handle the given delete event. This is the cascaded form. * * @param event The delete event. * @param transientEntities The cache of entities already deleted * @throws HibernateException */ public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { final EventSource source = event.getSession(); final PersistenceContext persistenceContext = source.getPersistenceContext(); Object entity = persistenceContext.unproxyAndReassociate(event.getObject()); EntityEntry entityEntry = persistenceContext.getEntry(entity); final EntityPersister persister; final Serializable id; final Object version; if (entityEntry == null) { LOG.trace("Entity was not persistent in delete processing"); persister = source.getEntityPersister(event.getEntityName(), entity); if (ForeignKeys.isTransient(persister.getEntityName(), entity, null, source)) { deleteTransientEntity( source, entity, event.isCascadeDeleteEnabled(), persister, transientEntities); // EARLY EXIT!!! return; } performDetachedEntityDeletionCheck(event); id = persister.getIdentifier(entity, source); if (id == null) { throw new TransientObjectException( "the detached instance passed to delete() had a null identifier"); } final EntityKey key = source.generateEntityKey(id, persister); persistenceContext.checkUniqueness(key, entity); new OnUpdateVisitor(source, id, entity).process(entity, persister); version = persister.getVersion(entity); entityEntry = persistenceContext.addEntity( entity, (persister.isMutable() ? Status.MANAGED : Status.READ_ONLY), persister.getPropertyValues(entity), key, version, LockMode.NONE, true, persister, false); } else { LOG.trace("Deleting a persistent instance"); if (entityEntry.getStatus() == Status.DELETED || entityEntry.getStatus() == Status.GONE) { LOG.trace("Object was already deleted"); return; } persister = entityEntry.getPersister(); id = entityEntry.getId(); version = entityEntry.getVersion(); } /*if ( !persister.isMutable() ) { throw new HibernateException( "attempted to delete an object of immutable class: " + MessageHelper.infoString(persister) ); }*/ if (invokeDeleteLifecycle(source, entity, persister)) { return; } deleteEntity( source, entity, entityEntry, event.isCascadeDeleteEnabled(), event.isOrphanRemovalBeforeUpdates(), persister, transientEntities); if (source.getFactory().getSettings().isIdentifierRollbackEnabled()) { persister.resetIdentifier(entity, id, version, source); } }