主义失去实体的持久性状态

时间:2015-05-15 14:59:21

标签: symfony doctrine-orm

我的实体是驱动程序位置。驱动程序可以有多个位置(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()'以获得线索。

更新

循环中的flushclear会导致问题。

正确保存了循环上方带有驱动程序实体的前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)];
}

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))