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