【发布时间】:2015-05-15 14:59:21
【问题描述】:
我的实体是driver和position。一个司机可以有很多位置(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 次迭代,驱动程序实体就不会被识别为受教义管理,并引发以下异常:
[学说\ORM\ORMInvalidArgumentException]
通过关系发现了一个新实体 'AppBundle\Entity\Position#driver' 未配置为级联 实体的持久化操作: AppBundle\Entity\Driver@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)];
}
【问题讨论】:
-
在
Drive类中有position属性吗?如果是,你真的需要吗?如果您在if (!($number % 100)) {之后执行var_dump($driver[0]),是否只显示类Driver? -
我才意识到这与驱动实体的变化无关。这是冲洗和清除。
标签: symfony doctrine-orm