Symfony3 - 在单个sql查询中更新多个实体

时间:2016-10-04 09:37:02

标签: php symfony

this old post反弹我正在寻找一种在一个SQL查询中更新几个Symfony entites的方法 - 出于优化原因。我有一个Content实体,以及一个服务中的方法,它可以更新所有兄弟"内容与setCurrent(0)。这是迄今为止的工作代码:

/**
 * Set given content the latest regarding its siblings
 */
public function setLatestContent(Entity\Content $content)
{
    // Get siblings entities
    $siblings = $this
        ->em
        ->getRepository('LPFrontRteBundle:Content')
        ->findBySibling($content);

    foreach ($siblings as $sibling_content) {
        $sibling_content->setCurrent(0);
    }

    $this->em->flush();
}

那很有效。但由于我有38个兄弟内容,我得到38个SQL查询,如:

UPDATE mr_content SET current = 0 WHERE id = 55
UPDATE mr_content SET current = 0 WHERE id = 56
UPDATE mr_content SET current = 0 WHERE id = 57
...

我想使用Doctrine"" clean"实体系统,以某种方式查询:

UPDATE mr_content SET current = 0 WHERE id = 55 OR id = 56 OR id = 57 ...

任何有关如何实现这一目标的想法 - 或者更聪明的解决方法都将受到高度赞赏。

修改

为了记录,这是我想出的 - 我喜欢它详细:) 使用$ qb作为查询构建器。

    $qb->update('LPFrontRteBundle:Content', 'c')
        ->set('c.current', 0)

        ->where('c.keyword = :keyword')
        ->setParameter('keyword', $content->getKeyword())

        ->andWhere('c.locale = :locale')
        ->setParameter('locale', $content->getLocale())

        ->andWhere('c.id != :id')
        ->setParameter('id', $content->getId())

        ->getQuery()->execute();

2 个答案:

答案 0 :(得分:5)

Batch processing是您正在寻找的。

Doctrine2中有两种批量更新方法。

第一个是DQL更新查询,最适合您。它会是这样的:

$q = $em->createQuery("UPDATE LPFrontRteBundle:Content c SET c.current = 0 WHERE id IN (:ids)")
        ->setParameter(':ids', $ids, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY));
$numUpdated = $q->execute();

答案 1 :(得分:1)

您可以收集所有ID并执行DQL以立即更新所有实体

$ids = array();
foreach ($siblings as $sibling_content) {
    $ids[] = $sibling_content->getId();
}

$this->em->createQuery("
    UPDATE
        LPFrontRteBundle:Content t
    SET
        t.current = 0
    WHERE
        t.id IN (:ids)
")
->setParameter(':ids', $ids, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
->execute();