阅读batch processing larger dataset in doctrine2,我偶然发现clear
方法。
在那里,使用了这个例子:
<?php
$batchSize = 20;
$i = 0;
$q = $em->createQuery('select u from MyProject\Model\User u');
$iterableResult = $q->iterate();
foreach ($iterableResult as $row) {
$user = $row[0];
$user->increaseCredit();
$user->calculateNewBonuses();
if (($i % $batchSize) === 0) {
$em->flush(); // Executes all updates.
$em->clear(); // Detaches all objects from Doctrine!
}
++$i;
}
$em->flush();
我很困惑clear
语句为什么会这样做,所提供的信息对我也没有帮助。
同时阅读代码,并没有帮助,因为我不明白它的意图。
这是doctrine2实际调用的内容:
/**
* Clears the UnitOfWork.
*
* @param string|null $entityName if given, only entities of this type will get detached.
*
* @return void
*/
public function clear($entityName = null)
{
if ($entityName === null) {
$this->identityMap =
$this->entityIdentifiers =
$this->originalEntityData =
$this->entityChangeSets =
$this->entityStates =
$this->scheduledForSynchronization =
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->collectionDeletions =
$this->collectionUpdates =
$this->extraUpdates =
$this->readOnlyObjects =
$this->visitedCollections =
$this->orphanRemovals = array();
if ($this->commitOrderCalculator !== null) {
$this->commitOrderCalculator->clear();
}
} else {
$visited = array();
foreach ($this->identityMap as $className => $entities) {
if ($className !== $entityName) {
continue;
}
foreach ($entities as $entity) {
$this->doDetach($entity, $visited, false);
}
}
}
if ($this->evm->hasListeners(Events::onClear)) {
$this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em, $entityName));
}
}
所以我的问题是:
对象与教义分离是什么意思?有什么影响?使用clear
有什么好处?
答案 0 :(得分:1)
查看学说参考文档,看起来clear()
将有效地释放它正在处理的所有对象的EntityManager
。
所以我的理解是flush()
提交数据库,clear()
从内存中释放(至少就教义而言)。
查看EntityManager
的{{1}}方法here和here (lines 421 to 435)的文档。反过来调用clear()
,
因此,对于UnitOfWork
,请查看here和here (lines 1881 an on)
仅供参考,您可以从文档(最新的2.5版本)获取UnitOfWork
中的代码:
EntityManager
和UnitOfWork:
/**
* Clears the EntityManager. All entities that are currently managed
* by this EntityManager become detached.
*
* @param string $entityName
*/
public function clear($entityName = null)
{
if ($entityName === null) {
$this->unitOfWork->clear();
} else {
//TODO
throw new ORMException("EntityManager#clear(\$entityName) not yet implemented.");
}
}
所以当文档说:
清除EntityManager。当前由此EntityManager管理的所有实体都将分离。
我的理解是,他们所说的“超然”是指实体经理不再保留这些实体的记录。因此,如果没有其他任何内容,他们可以收集垃圾。
如果你想确保它确实收集垃圾并有效地释放内存,那么你最好在/**
* Clears the UnitOfWork.
*/
public function clear()
{
$this->identityMap =
$this->entityIdentifiers =
$this->originalEntityData =
$this->entityChangeSets =
$this->entityStates =
$this->scheduledForDirtyCheck =
$this->entityInsertions =
$this->entityUpdates =
$this->entityDeletions =
$this->collectionDeletions =
$this->collectionUpdates =
$this->extraUpdates =
$this->readOnlyObjects =
$this->orphanRemovals = array();
if ($this->commitOrderCalculator !== null) {
$this->commitOrderCalculator->clear();
}
if ($this->evm->hasListeners(Events::onClear)) {
$this->evm->dispatchEvent(Events::onClear, new Event\OnClearEventArgs($this->em));
}
}
进程循环的某个地方调用gc_collect_cycles()
。