Php Doctrine2-一次插入多个

Php Doctrine2-一次插入多个,php,mysql,symfony,doctrine-orm,Php,Mysql,Symfony,Doctrine Orm,我是个新手,对我来说还有一些模糊的领域。在本例中,我使用循环和实体管理器在数据库中插入新记录。它工作得很好,但我注意到条令按实体生成一个插入查询,这可能会变得非常庞大 使用Doctrine2和symfony2.3,我想知道如何设置它,使它只生成一个包含所有值的insert查询(当然,我们只讨论一个实体) 我的意思是改变这一点: INSERT INTO dummy_table VALUES (x1, y1) INSERT INTO dummy_table VALUES (x2, y2)

我是个新手,对我来说还有一些模糊的领域。在本例中,我使用循环和实体管理器在数据库中插入新记录。它工作得很好,但我注意到条令按实体生成一个插入查询,这可能会变得非常庞大

使用Doctrine2和symfony2.3,我想知道如何设置它,使它只生成一个包含所有值的insert查询(当然,我们只讨论一个实体)

我的意思是改变这一点:

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

这是我的密码:

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

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

$em->flush();

我还没有测试过它,但似乎可以用一个集合来测试它

$collection = new Doctrine_Collection('tablename');
$collection->add($record1);
$collection->add($record2);
$collection->add($record3);
$collection->add($record4);
$collection->save();
当然,您应该在循环中使用add。根据,Doctrine2不允许您将多个INSERT语句组合成一个:

有些人似乎想知道为什么教义没有使用 多重插入(插入到(…)值(…),(…),(…),(…)

首先,这种语法仅在mysql和更高版本上受支持 第二,没有简单的方法可以掌握所有 使用时,在这种多插入中生成的标识符 自动递增或串行,ORM需要标识 管理对象。最后,插入性能很少是最重要的 ORM的瓶颈。普通插入的速度足以 大多数情况下,如果您真的想快速批量插入,那么 多插入并不是最好的方式,例如Postgres COPY或Mysql 加载数据填充要快几个数量级

这些就是为什么不值得努力实施 在一个数据库中对mysql和postgresql执行多插入的抽象 奥姆

您可以在此处阅读有关Doctrine2批处理的更多信息:

您可以切换到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();

你可以试试这个fork。它完全实现了你想要的。我在MySQL中测试了它,它工作得很好,比批处理快5倍。这个fork获得第一个插入的id,并在php中增加它以获得其他id。它适用于大多数情况,但不是所有情况。所以你需要了解使用这个fork时你在做什么。

可以使用
executeUpdate($query,array$params=array(),array$types=array())
DriverConnection接口的方法来执行此操作。但是绑定多个参数并不难

数据:

批量更新方法:

public function updateOrCreateBulk($posts, \Doctrine\DBAL\Connection $connection)
{

    $placeholders = [];
    $values = [];
    $types = [];

    foreach ($posts as $columnName => $value) {
        $placeholders[] = '(?)';
        $values[] = array_values($value);
        $types[] = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY;
    }

    return $connection->executeUpdate(
        'INSERT INTO `wp_postmeta` (`post_id`, `meta_key`, `meta_value`)  VALUES ' . implode(', ', $placeholders) . ' ON DUPLICATE KEY UPDATE `meta_value` = VALUES(`meta_value`)',
        $values,
        $types
    );
}

你会把这些查询合并成一个查询吗?我在考虑性能改进。这只是一个例子,在实践中,很可能需要插入20个实体。因此,只创建连接要比n个连接快得多。编辑:我发现了这个主题。我可能会警告你,条令增加了很多多余的内容ead在您所做的每一个插入上(管理状态等),因此对于真正大的插入,我会选择DBAL查询而不是ORM关系。//就我的2个中心,我会尝试一下,但是如果每次我要插入多个值时都必须指定表名,那就太“复杂”了谢谢,现在我知道通过条令是不可能的。+1刷新剩余的对象…文档应该包括这一点,就好像你的批处理大小小于结果数量一样。什么都没有发生请注意
$em->clear()
可能会对功能中未直接处理的其他实体产生错误影响。例如,您可以通过与产品类别用户的关系获得一些异常……因此,只清除具有所需类型的实体更方便。在这种情况下,它将是
$em->clear('Product')
$postMetaData = [
    [
        'post_id' => $product->getId(),
        'meta_key' => '_visibility',
        'meta_value' => 'visible',
    ],
    [
        'post_id' => $product->getId(),
        'meta_key' => '_stock_status',
        'meta_value' => $insert['in_stock'] ? 'instock' : 'outofstock',
    ]
];
public function updateOrCreateBulk($posts, \Doctrine\DBAL\Connection $connection)
{

    $placeholders = [];
    $values = [];
    $types = [];

    foreach ($posts as $columnName => $value) {
        $placeholders[] = '(?)';
        $values[] = array_values($value);
        $types[] = \Doctrine\DBAL\Connection::PARAM_INT_ARRAY;
    }

    return $connection->executeUpdate(
        'INSERT INTO `wp_postmeta` (`post_id`, `meta_key`, `meta_value`)  VALUES ' . implode(', ', $placeholders) . ' ON DUPLICATE KEY UPDATE `meta_value` = VALUES(`meta_value`)',
        $values,
        $types
    );
}