Doctrine orm Doctrine2:PreFlush钩子没有超时

Doctrine orm Doctrine2:PreFlush钩子没有超时,doctrine-orm,symfony4,timeoutexception,Doctrine Orm,Symfony4,Timeoutexception,我有两个实体 首先是我的父实体,它有一个名为productsCount的属性。 此实体有另一个与之链接的实体,称为Store和Store have linked Room。每个房间可以有多个产品 编辑分配给文件室的产品时,我希望更新父产品count以存储所有商店中所有文件室中所有产品的计数 我有一个计算计数的SQL查询。每次我用新产品更新房间时,我都需要这样做。这是通过使用房间实体上的EntityListener使用preFlush钩子完成的 preFlush钩子被正确触发,但由于某种原因它将超

我有两个实体

首先是我的父实体,它有一个名为productsCount的属性。 此实体有另一个与之链接的实体,称为Store和Store have linked Room。每个房间可以有多个产品

编辑分配给文件室的产品时,我希望更新父产品count以存储所有商店中所有文件室中所有产品的计数

我有一个计算计数的SQL查询。每次我用新产品更新房间时,我都需要这样做。这是通过使用房间实体上的EntityListener使用preFlush钩子完成的

preFlush钩子被正确触发,但由于某种原因它将超时

下面是preFlush代码示例

    public function preFlush(Room $room, PreFlushEventArgs $args)
  {
    $em = $args->getEntityManager();
    $parent = $room->getStore()->getParent();
    $rsm = new ResultSetMapping();
    $rsm->addScalarResult('COUNT(product_id)', 'count');

    $query = $em->createNativeQuery(
      'select COUNT(product_id)
            from room_product where `room_id` in
            (select id from room where store_id in
            (select id from store where parent_id = :parentId))', $rsm);
    $query->setParameter('parentId', $parent->getId());
    $result = $query->getOneOrNullResult();
    $parent->setNumberOfServices($result['count']);
    $em->persist($parent);
    $em->flush();
  }
查询应该可以正常工作,所以我认为它与刷新和持久化父实体有关


有什么想法吗?

原因是递归:您正在调用
$em->flush()
从订阅服务器,EntityManager进入
flush
,触发
preFlush
事件,该事件调用处理程序,该处理程序再次调用
$em->flush()
,依此类推


IIRC preFlush是在更改集计算之前调用的,因此仅用新值更新实体就足以让条令检测到所述更改。

因此,经过几个小时的战斗,我找到了解决方案

事实证明,我不必坚持,也不必冲淡变化。解决方案是使用工作单元重新计算$parent上的更改,然后条令将自行刷新这些更改。我还必须改变我计算产品的方式,因为在preFlush阶段,更改尚未出现在数据库中,因此查询将无法正常工作。这就是为什么我通过遍历关系树来手动计算它们

下面是一个代码示例

public function preFlush(Room $room, PreFlushEventArgs $args)
  {
    $em = $args->getEntityManager();
    $numOfProducts = 0;
    $parent = $room->getStore()->getParent();
    foreach($parent->getStores() as $store) {
      foreach($store->getRooms() as $room) {
        $numOfServices += count($room->getProducts());
      }
    }
    $parent->setNumberOfProducts($numOfProducts);
    $classMetadata = $em->getClassMetadata(get_class($parent));
    $em->getUnitOfWork()->computeChangeSet($classMetadata, $parent);
  }

我注释掉了persist和flush,但是$parent没有被保存