2016-10-04 37 views
1

this old post反弹我正在寻找一种方法来更新一个SQL查询中的几个Symfony实体 - 为了优化原因。我有一个Content实体和一个服务中的方法,它使用setCurrent(0)更新所有“同级”内容。这是迄今为止的工作代码:Symfony3 - 在单个SQL查询中更新多个实体

/** 
* 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 
... 

我想用主义的“干净”的实体制度,办法有一个查询,如:

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(); 

回答

4

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(); 
+0

谢谢!我终于与一个非常接近的解决方案,我会发布,但这确实是我一直在寻找:) – LoicPenn

1

您可以收集所有的IDS和执行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(); 
+0

谢谢!我所做的是跳过“实体提取”部分直接从查询中更新。我阅读Repos只是为了“取材”的目的,但也许这只是一个哲学问题? – LoicPenn

+0

我认为你是对的,而且有些服务更适用于这样的操作。在我的项目中,为了简单起见,我在存储库中放置了这样的操作:)我将删除我的答案的第二部分,不要混淆其他用户 –