嵌套实体中的 Doctrine EntityManager clear 方法

Doctrine EntityManager clear method in nested entities

我想使用 doctrine batch insert processing 来优化大量实体的插入。问题在于 Clear 方法。它表示此方法分离由 EntityManager 管理的所有实体。那么在我有一个 parent 实体的情况下,我应该怎么做,它有很多 child,并且每个 child 都有它们的 child,像这样:

所以我有 1 个 rideSession,3 个轨道,每个轨道有 2000 个点。我可以在负责保存点的最后一个循环中使用批处理。但是如果我使用clear方法,那么如何为点和轨迹设置parents呢?清除方法将分离它们,对吗?

如果您的所有 40000 个对象都已加载到内存中,那么您可以直接使用代码而无需清除。清除实体管理器用于优化 PHP 脚本中的内存。如果您有足够的内存来存储所有对象,则根本不需要清除实体管理器。

在这种情况下要优化内存,您可以在每次坚持后unset($entity)

为了适应数据库连接带宽,您可以将多个实体分组,如示例所示。

$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
    $em->persist($entities[$i]);
    unset($entities[$i]);
    if (($i % $batchSize) === 0) {
        $em->flush();
    }
}
$em->flush(); //Persist objects that did not make up an entire batch

很快您将达到内存限制。分批flush()的想法是可以的,但是你需要在每批结束时clear()EntityManager来释放使用的内存。

但在你的情况下,如果你在 $entityManager->clear(); 之后调用 $child->setParent($parent);,你将有 ORMInvalidArgumentException(a.k.a。"new entity foung through relationship")。 =24=]

问题是 $parent 现在在 UnitOfWork 中处于 detached 状态。所以你需要把它再次置于 managed 状态。这可以通过使用 $entityManager->merge(); 或简单地使用 $parentRepository->find($parent->getId()); 来完成。

只需确保在每次 clear() 之后将所有实体调至 managed 状态,以防您稍后要使用它们。