在postRemove Listener中创建的实体不会保留

时间:2018-05-02 15:07:34

标签: symfony doctrine

我正在开发一个基于Symfony 2.8的项目,该项目基本上是一个在线地址簿。

EntityDeletionListener用于处理postRemove事件,以便将某些信息添加到删除日志中,这是一些内部簿记所需的:

class EntityDeletionListener implements EventSubscriber {
    public function getSubscribedEvents() {
        return array('postRemove');
    }

    public function postRemove(LifecycleEventArgs $args) {
        $entity = $args->getEntity();

        if (!$entity->shouldAddToDeleteLog())
           return ;

        $em = $args->getEntityManager();
        $repo = $em->getRepository('AppBundle:DeleteLog');

        $log = $repo->createEntity();
        $log->setGuid($entity->getGuid());
        ...

        $em->persist($log);

        // Flush entity manager if not disabled in entity settings
        if ($entity->shouldFlushDeleteLog())
            $em->flush();
    }
}

这没有任何问题:每次删除Contact实体时,都会自动创建删除日志条目。

现在我正在开发一个批量删除任意数量的选定Contacts的选项。 为了加快处理速度,实体管理器不会在每次删除操作后刷新,而是仅在处理完一些批处理后才刷新。

class ContactRepository extends EntityRepository {
    public function bulkDelete($guids) {
        $this->_em->getConnection()->beginTransaction();

        try {
            $batchSize = 100;
            $currentBatch = 0;           

            foreach ($guids as $guid) {
                $contact = $this->findOneByGuid($guid);

                if ($contact) {        
                    // DO NOT FLUSH EVERY DELETE LOG
                    $contact->setDeleteLogFlush(false);

                    $this->_em->remove($contact);

                    $currentBatch++;
                    if ($currentBatch % $batchSize === 0)
                        $this->_em->flush();
                }
            }

            $this->_em->flush();  
            $this->_em->getConnection()->commit();
        } catch (\Exception $ex) {            
            $this->_em->getConnection()->rollBack();
            return false;
        }
    }
}

问题1: 如果我使用$contact->setDeleteLogFlush(false)来避免自动刷新每个DeleteLog,则DeleteLogs根本不会保留。此外,Contact实体被正确删除,并且每次删除操作都会执行postRemove,日志不会持久保存到数据库。

没有异常或其他错误可以解释为什么日志不会持久化。即使存在错误,在这种情况下,完整的事务也会失败,并且Contacts也不会被删除。但它们被删除了......

问题2: 如果不使用$contact->setDeleteLogFlush(false) postRemove侦听器刷新每个新DeleteLog,只要一次删除多个条目,我就会收到以下异常:

Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalThrowableError: "Type error: Argument 2 passed to Doctrine\DBAL\Connection::delete() must be of the type array, null given

如何解决这个问题?为什么在刷新实体管理器时,postRemove侦听器中创建的日志不会保留?

1 个答案:

答案 0 :(得分:0)

我认为问题在于您要创建和删除多个Contact实体,但是您在错误的事件中执行此操作,因为正如documentation中所述

  

实体发生后,实体发生postRemove事件   删除。它将在数据库删除操作后调用。它   没有调用DQL DELETE语句。

并且您不应对stated here

对数据库进行任何更改
  

postUpdate,postRemove,postPersist

     

在EntityManager#flush()中调用三个post事件。变化   在这里与数据库中的持久性无关,但是你   可以使用这些事件来更改非可持久化项目,例如非映射项目   字段,日志记录甚至不是直接关联的类   由Doctrine映射。

因此,我将整个postRemove逻辑移至preRemove事件,因为

  

当传递给每个实体时,会调用preRemove事件   EntityManager #remove()方法。它适用于所有协会   被标记为级联删除。