Getting a managed and dirty entity error on persist

问题描述 投票:0回答:1

我有以下代码:

$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 条记录。我得到了订单参考,然后是它设置的支付计划。我也查看数据库,我的记录在那里更新。但是,从第 1001 行开始的那一刻,我收到以下错误:

  [Doctrine\ORM\ORMInvalidArgumentException]                                      
  A managed+dirty entity 57b6fed7b4ad7 can not be scheduled for insertion. 

该 ID 与订单参考匹配。

我首先认为这可能是实体 1001 的问题,所以将我的批量大小更改为 50,然后它发生在它试图保存的第 51 个实体上。这几乎就像

$em->clear();
没有做它应该做的事。

有什么办法可以解决这个问题吗?

php symfony doctrine symfony-2.8
1个回答
0
投票

如果您的订单来自使用存储库功能的数据库,首先清除它们。这就是为什么在第一批 1000 之后没有任何工作了。 学说得到 mindfu****。哈哈

但你离解决方案不远了。

在你的函数之上尝试这样的东西

 $orders = $this->$orderRepository->findAll();
 $orderIds = array_map(function (Order $value) {
                return $value->getId();
 }, $orders);

 // this way you only iterate over an array of ids
 $this->em->clear() // detach all orders from entity manager : freeing memory
 $count = 0;
 foreach($orderIds => $orderId){
   
    $order = $this->$orderRepository->find($orderId);
    // your code here
 }

这样您也可以实现您的目标:通过释放内存来保持大型记录的性能。

提示:

->persist($object)
仅对新实体有用。如果你的对象来自任何存储库函数,它已经被持久化了。

这个答案非常适合中大型数据集。 由于

->find()
,您的查询量将等于记录量。这对于非常大量的数据可能是不利的。由于通过 id 查询在良好和最新的数据库版本中非常快,这可能就足够了。

但是对于非常大和非常大的数据集。使用批处理方法也很简单:https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/batch-processing.html#iterating-results 或者
https://www.doctrine-project.org/projects/doctrine-orm/en/2.14/reference/batch-processing.html#iterating-results

© www.soinside.com 2019 - 2024. All rights reserved.