我正在尝试这里描述的批处理方法: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html
我的代码看起来像这样
$limit = 10000;
$batchSize = 20;
$role = $this->em->getRepository('userRole')->find(1);
for($i = 0; $i <= $limit; $i++)
{
$user = new \Entity\User;
$user->setName('name'.$i);
$user->setEmail('email'.$i.'@email.blah');
$user->setPassword('pwd'.$i);
$user->setRole($role);
$this->em->persist($user);
if (($i % $batchSize) == 0) {
$this->em->flush();
$this->em->clear();
}
}
问题是,在第一次调用em-&gt; flush()之后也是如此
$ role被分离,每20个用户使用一个新的id作为新角色
创造,这不是我想要的
这种情况有没有可用的解决方法?只有一个我能做的工作就是每次在循环中获取用户角色实体
谢谢
答案 0 :(得分:15)
clear()
分离由实体管理器管理的所有实体,因此$role
也被分离,并且尝试持久化分离的实体会创建一个新实体。
您应该在清除后再次获取角色:
$this->em->clear();
$role = $this->em->getRepository('userRole')->find(1);
或者只是创建一个引用:
$this->em->clear();
$role = $this->em->getReference('userRole', 1);
答案 1 :(得分:1)
作为arnaud576875的答案的替代方案,您可以从实体管理器中分离 $ user,以便可以立即进行GC。像这样:
$this->em->flush();
$this->em->detach($user);
修改强>
正如Geoff所指出的,只会分离最新的创建的用户对象。所以这种方法不推荐。
答案 2 :(得分:0)
另一种选择是merge
角色在明确后回复:
if (($i % $batchSize) == 0) {
$this->em->flush();
$this->em->clear();
$this->em->merge($role);
}
我不确定merge()是多么昂贵 - 如果我不得不猜测,我会选择arnaud建议使用getReference()