2016-04-25 91 views
2

我有以下一段代碼將某些帖子導入到我的數據庫中。它檢查一個帖子是否已經存在。如果不是這樣,它會創建一個新的。使用多個Doctrine實例重複行

此腳本運行在cron作業中。但是,有時它也必須手動運行。可能發生這個腳本的兩個實例同時運行。發生這種情況時,將創建重複記錄。我看不出爲什麼會這樣。

foreach ($posts as $post) { 
    $entity = new Post(); 
    $entity 
     ->setName($post->name) 
     ->setGender($post->gender()) 
     ->setDate(new \DateTime()) 
    ; 

    $em = $this->getContainer()->get('doctrine')->getManager(); 
    $checkEntity = $em->getRepository('SampleBundle:Post')->findOneBy(array(
     'name' => $post->name 
    )); 

    if (!$checkEntity) { 
     $em = $this->getContainer()->get('doctrine')->getManager(); 
     $em->persist($entity); 
     $em->flush(); 
    } 
} 

有人可以在這個問題上點點滴滴嗎?

回答

1

1)最簡單的解決方案是防止同時運行相同的命令。 你可以使用https://github.com/ffreitas-br/command-lock-bundle

2)可以正好趕上例外的foreach:

$em->persist($entity); 

try { 
    $em->flush(); 
} catch(UniqueConstraintViolationException $e) { 
    // Detach object to prevent exception with same entity on next flush() call. 
    $em->detach($entity); 
} 

如果需要保存只有一個實體實例:

$em->persist($entity); 

try { 
    $em->flush($entity); 
} catch(UniqueConstraintViolationException $e) { 
    // Nothing. 
} 

3)如果你想獲得性能優勢運行兩條命令並行思考消息隊列。 https://github.com/videlalvaro/RabbitMqBundle

監製:

foreach ($users as $user) { 
    $producer->produce(new Message($user['name'])); 
} 

消費者:

$name = $message->getName(); 

$entity = new Post(); 
$entity 
    ->setName($name) 
; 

$em = $this->getContainer()->get('doctrine')->getManager(); 
$em->persist($entity); 
$em->flush(); 
+0

如果我使用'UniqueConstraintViolationException'我應該讓我的實體的任何調整? – Peter

+0

謝謝你好,答案已更新,添加detach()調用。 –