public function flush($remoteOperations = null, $fetchMode = null) { // If $remoteOperations is null, flush() has been called from a server-side method so we don't want to clear the em if ($remoteOperations) { $this->em->clear(); } // Start the transaction $this->em->getConnection()->beginTransaction(); try { // Perform the flush $flushExecutor = new FlushExecutor($this->em, $remoteOperations, $this->deserializationWalker); $changeSets = $flushExecutor->flush(); // Go through the elements in the change sets making the entities Flextrine ready (apart from temporaryUidMap and entityDeletionIdMap which are not entities) if ($fetchMode) { $this->setFetchMode($fetchMode); } foreach ($changeSets as $changeSetType => $changeSet) { if ($changeSetType != "temporaryUidMap" && $changeSetType != "entityDeletionIdMap") { foreach ($changeSet as $oid => $entity) { $changeSet[$oid] = $this->flextrinize($entity); } } } // Commit the transaction $this->em->getConnection()->commit(); // Return the change sets so they can be replicated in Flextrine return $changeSets; } catch (\Exception $e) { $this->em->getConnection()->rollback(); $this->em->close(); throw $e; } }
/** * Commits the UnitOfWork, executing all operations that have been postponed * up to this point. The state of all managed entities will be synchronized with * the database. * * The operations are executed in the following order: * * 1) All entity insertions * 2) All entity updates * 3) All collection deletions * 4) All collection updates * 5) All entity deletions * */ public function commit() { // Compute changes done since last commit. $this->computeChangeSets(); if (!($this->entityInsertions || $this->entityDeletions || $this->entityUpdates || $this->collectionUpdates || $this->collectionDeletions || $this->orphanRemovals)) { return; // Nothing to do. } if ($this->orphanRemovals) { foreach ($this->orphanRemovals as $orphan) { $this->remove($orphan); } } // Raise onFlush if ($this->evm->hasListeners(Events::onFlush)) { $this->evm->dispatchEvent(Events::onFlush, new Event\OnFlushEventArgs($this->em)); } // Now we need a commit order to maintain referential integrity $commitOrder = $this->getCommitOrder(); $conn = $this->em->getConnection(); $conn->beginTransaction(); try { if ($this->entityInsertions) { foreach ($commitOrder as $class) { $this->executeInserts($class); } } if ($this->entityUpdates) { foreach ($commitOrder as $class) { $this->executeUpdates($class); } } // Extra updates that were requested by persisters. if ($this->extraUpdates) { $this->executeExtraUpdates(); } // Collection deletions (deletions of complete collections) foreach ($this->collectionDeletions as $collectionToDelete) { $this->getCollectionPersister($collectionToDelete->getMapping())->delete($collectionToDelete); } // Collection updates (deleteRows, updateRows, insertRows) foreach ($this->collectionUpdates as $collectionToUpdate) { $this->getCollectionPersister($collectionToUpdate->getMapping())->update($collectionToUpdate); } // Entity deletions come last and need to be in reverse commit order if ($this->entityDeletions) { for ($count = count($commitOrder), $i = $count - 1; $i >= 0; --$i) { $this->executeDeletions($commitOrder[$i]); } } $conn->commit(); } catch (Exception $e) { $this->em->close(); $conn->rollback(); throw $e; } // Take new snapshots from visited collections foreach ($this->visitedCollections as $coll) { $coll->takeSnapshot(); } // Clear up $this->entityInsertions = $this->entityUpdates = $this->entityDeletions = $this->extraUpdates = $this->entityChangeSets = $this->collectionUpdates = $this->collectionDeletions = $this->visitedCollections = $this->scheduledForDirtyCheck = $this->orphanRemovals = array(); }
/** * Rollback any database changes made during the current transaction. * * @throws Doctrine\DBAL\ConnectionException If the rollback operation failed. */ public function rollback() { $this->_em->close(); $this->_conn->rollback(); }