Doctrine orm 保留实体而不将其附加到EntityManager

Doctrine orm 保留实体而不将其附加到EntityManager,doctrine-orm,Doctrine Orm,我想从XML文件大容量导入实体 XML文件可能非常大(最多100万个实体),因此我无法以传统方式保留所有实体: $em->beginTransaction(); 而($entity=$xmlReader->readNextEntity()){ $em->persist($entity); } $em->flush(); $em->commit(); 我很快就会超过我的内存限制,而且该原则并不是真正设计用来处理这么多托管实体的 我不需要跟踪对持久化实体的更改,只需要持久化它们;因此,我不希望他们

我想从XML文件大容量导入实体

XML文件可能非常大(最多100万个实体),因此我无法以传统方式保留所有实体:

$em->beginTransaction();
而($entity=$xmlReader->readNextEntity()){
$em->persist($entity);
}
$em->flush();
$em->commit();
我很快就会超过我的内存限制,而且该原则并不是真正设计用来处理这么多托管实体的

我不需要跟踪对持久化实体的更改,只需要持久化它们;因此,我不希望他们由EntityManager管理

是否可以在不让EntityManager管理的情况下持久化实体?


我想到的第一个选择是在坚持之后立即将其分离:

$em->beginTransaction();
而($entity=$xmlReader->readNextEntity()){
$em->persist($entity);
$em->flush($entity);
$em->detach($entity);
}
$em->commit();
但这在理论上是相当昂贵的,并且会减缓进口



另一种选择是使用
连接
对象和准备好的语句直接将数据插入数据库,但我喜欢实体的抽象,理想情况下希望直接存储对象。

而不是在每次插入后使用
分离
刷新
,您可以批量调用
clear
(将所有实体从管理器中分离)和
flush
,这应该会更快:

条令中的批量插入最好分批执行,以 事务性写后行为的优点 实体管理器。下面的代码显示了插入10000的示例 批处理大小为20的对象。您可能需要尝试使用 批量大小,以找到最适合您的大小。大批量 大小意味着更多准备好的语句在内部重用,但也意味着更多 冲水时工作

如果可能,我建议避免批量操作的事务,因为它们往往会减慢速度:

//$em->beginTransaction();
$i = 0;

while ($entity = $xmlReader->readNextEntity()) {
    $em->persist($entity);
    if(++$i % 20 == 0) {
        $em->flush();
        $em->clear(); // detaches all entities
    }
}

$em->flush(); //Persist objects that did not make up an entire batch
$em->clear();

//$em->commit();

我本来希望让EntityManager保持目前的状态,但这毕竟不是什么大问题。我还看到,
clear()
接受一个可选的类名,只分离给定类的实体,这在这种情况下很有用。所以我想这是目前唯一的办法!