我有以下代码:
$count = 0;
/** @var Order $order */
foreach ($orders as $order) {
$output->write(sprintf('Processing order %s... ', ($count + 1), $order->getReference()));
if ($this->shouldSkip($order)) {
$output->writeln('Doesn\'t meet criteria, skipping.');
continue;
}
$paymentPlanName = PayoutPlanFactory::make($order)->getPayoutPlanName();
$output->write(sprintf('Setting payment plan to %s...', $paymentPlanName));
$order->setPayoutPlan($paymentPlanName);
$em->persist($order);
$output->writeln(' Done.');
if ((++$count % 1000) === 0) {
$output->write('Flushing records... ');
$em->flush();
$output->writeln('Done.');
$output->write('Clearing em... ');
$em->clear();
$output->writeln('Done.');
}
}
$em->flush();
$em->clear();
当我运行这个命令时,输出结果与我期望的前1000条记录完全一致。我得到了订单参考,然后是它设置的支付计划。我也在DB中查找,我的记录在那里更新。但是,当它从第1001行开始时,我得到以下错误:
[Doctrine\ORM\ORMInvalidArgumentException]
A managed+dirty entity 57b6fed7b4ad7 can not be scheduled for insertion.
该ID与订单参考匹配。
我首先想到这可能是实体1001的问题,所以将批处理大小更改为50,然后它发生在它试图保存的第51个实体上。这几乎就像$em->clear();
没有做它应该做的事情。
有什么方法可以解决这个问题吗?
1条答案
按热度按时间zxlwwiss1#
如果您的订单来自使用存储库功能的数据库,首先清除分离它们.这就是为什么在第一批1000个之后,什么都不工作了。教条让人头脑发热。哈哈
但你离解决方案不远了。
在你的函数之上尝试类似这样的东西
这样你也能实现你的目标:通过释放内存来保持对大记录的性能。
很高兴知道:
->persist($object)
仅对新实体有用。如果你的对象来自任何一个存储库函数,那么它已经被持久化了.这个答案非常适合中型到大型数据集。由于
->find()
,您将拥有与记录数量相等的查询数量。这对于非常大量的数据来说可能是不好的。由于在良好和最新的数据库版本中通过id查询非常快,因此这可能就足够了。但对于非常大和非常大的数据集。使用分批法的学说也很简单: www.example.com 或
www.example. com