Doctrine2 - 一次多次插入

新手上路,请多包涵

我是 Doctrine 的新手,对我来说仍然有一些模糊的地方。在这种情况下,我使用循环和实体管理器在数据库中插入新记录。它工作正常,但我注意到 Doctrine 按实体进行插入查询,这可能会变得非常庞大。

使用 Doctrine2 和 Symfony 2.3,我想知道我们如何设置它,以便它只进行 1 个插入查询,其中包含所有值(当然我们只讨论 1 个实体)。

我的意思是改变这个:

 INSERT INTO dummy_table VALUES (x1, y1)
INSERT INTO dummy_table VALUES (x2, y2)

进入

INSERT INTO dummy_table VALUES (x1, y1), (x2, y2)

这是我的代码:

 $em = $this->container->get('doctrine')->getManager();

foreach($items as $item){
    $newItem = new Product($item['datas']);
    $em->persist($newItem);
}

$em->flush();

原文由 Molkobain 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 473
2 个回答

根据 这个答案,Doctrine2 不允许您将多个 INSERT 语句合并为一个:

有些人似乎想知道为什么 Doctrine 不使用 multi-inserts (insert into (…) values (…), (…), (…), …

首先,此语法仅在 mysql 和较新的 postgresql 版本上受支持。其次,在使用 AUTO_INCREMENT 或 SERIAL 时,没有简单的方法来获取此类多插入中所有生成的标识符,并且 ORM 需要标识符来进行对象的身份管理。最后,插入性能很少成为 ORM 的瓶颈。普通插入对于大多数情况来说已经足够快了,如果你真的想做快速批量插入,那么多插入并不是最好的方法,即 Postgres COPY 或 Mysql LOAD DATA INFILE 快几个数量级。

这些就是为什么不值得努力在 ORM 中实现对 mysql 和 postgresql 执行多插入的抽象的原因。

您可以在此处阅读有关 Doctrine2 批处理的更多信息: https ://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html

您可以切换到 DBAL 或通过在插入一定数量后刷新实体管理器来小批量处理数据:

 $batchSize = 20;

foreach ($items as $i => $item) {
     $product = new Product($item['datas']);

     $em->persist($product);

     // flush everything to the database every 20 inserts
     if (($i % $batchSize) == 0) {
         $em->flush();
         $em->clear();
    }
}

// flush the remaining objects
$em->flush();
$em->clear();

原文由 ukliviu 发布,翻译遵循 CC BY-SA 4.0 许可协议

你可以试试这个分支 https://github.com/stas29a/doctrine2 。它完全实现了您想要的。我在 MySQL 中对其进行了测试,它工作正常并且比批处理快 5 倍。这个 fork 获得第一个插入的 id 并在 php 中递增它以获得其他 id。它适用于大多数情况,但不适用于所有情况。所以你需要明白你在使用这个叉子的时候在做什么。

原文由 s29a 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏