使用多个Doctrine实例重复行

时间:2016-04-25 10:37:34

标签: php symfony doctrine-orm

我有以下代码将某些帖子导入我的数据库。它会检查帖子是否已存在。如果不是这种情况,它将创建一个新的。

此脚本在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 个答案:

答案 0 :(得分: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();