我的实体是驱动程序和位置。驱动程序可以有多个位置(gps数据)。我的司机回购中也有一个方法,它给了我所有司机最新的位置。
public function getDriversWithCurrentPosition()
{
$qb = $this->createQueryBuilder('d');
$qb
->select('d, p.lat, p.lng')
->leftJoin('d.positions', 'p')
->where('p.timeCreated = (SELECT MAX(p2.timeCreated) FROM AppBundle\Entity\Position p2 WHERE p2.driver = d) OR p.timeCreated IS NULL')
->groupBy('p.driver')
;
return $qb->getQuery()->getResult();
}
现在我编写了一个symfony命令来为所有现有驱动程序生成随机位置。该命令生成假设1000个位置实体并在每100次迭代后刷新,并且还随机更改相关驱动程序。
/**
* The returned drivers array looks like this:
* [
* [0 => driver-entity, 'lat' => 52.5634, 'lng' => 8.4535],
* [0 => driver-entity, 'lat' => 52.7434, 'lng' => 8.3434],
* ...
* ]
*/
$drivers = $driverRepo->getDriversWithCurrentPosition();
$driver = $drivers ? $drivers[0] : null;
$number = 1000;
while ($number) {
// generate new lat/lng based on drivers current position
$lat = $driver['lat'] + ...;
$lng = $driver['lng'] + ...;
// creating new entity
$position = new Position();
$position->setDriver($driver[0]);
$position->setLat($lat);
$position->setLng($lng);
$this->em->persist($position);
if (!($number % 100)) {
$this->em->flush();
$this->em->clear();
// change driver
$driver = $drivers[rand(0, count($drivers) - 1)];
}
$number--;
}
$this->em->flush();
$this->em->clear();
因此,此命令生成的每100个位置实体,相关的驱动程序实体应该更改。但是,只要它进入第101次迭代,驱动程序实体就不会被识别为由doctrine管理,并抛出以下异常:
[学说\ ORM \ ORMInvalidArgumentException]
通过这种关系找到了一个新实体 'AppBundle \ Entity \ Position#driver'未配置为级联 坚持实体运营: 的appbundle \实体\驱动@ 000000003412a11000007f77533bcf9d。要解决 此问题:在此显式调用EntityManager#persist() 未知实体或配置级联持久化此关联 映射例如@ManyToOne(..,cascade = {“persist”})。如果你不能 找出导致问题实施的实体 'AppBundle \ Entity \ Driver #__ toString()'以获得线索。
更新
循环中的flush
和clear
会导致问题。
正确保存了循环上方带有驱动程序实体的前100个位置实体。
当我改变
$position->setDriver($driver[0]);
到
$position->setDriver($driverRepo->find($driver[0]->getId()));
它有效。
有关如何解决此问题的任何建议?
更新2
快速解决方法是刷新lopp中的驱动程序数组:
if (!($number % 100)) {
$this->em->flush();
$this->em->clear();
// change driver
$drivers = $driverRepo->getDriversWithCurrentPosition();
$driver = $drivers[rand(0, count($drivers) - 1)];
}
答案 0 :(得分:0)
冲洗时不要清除。
if (!($number % 100)) {
$this->em->flush();
$this->em->clear(); <-HERE IS THE PROBLEM
// change driver
$driver = $drivers[rand(0, count($drivers) - 1)];
}
仅在命令末尾调用clear。 如果你担心内存消耗,那么只清除某些实体(你的情况下的$位置,但是你必须将它们保存在一个数组中,然后迭代它并用$ this-em-&gt;清除它们。清楚($ position))