【问题标题】:Doctrine losing persistence state of entity实体失去持久性状态的学说
【发布时间】:2015-05-15 14:59:21
【问题描述】:

我的实体是driverposition。一个司机可以有很多位置(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()' 来获得线索。

更新

是循环内的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)];
}

【问题讨论】:

  • Drive 类中有position 属性吗?如果是,你真的需要吗?如果您在if (!($number % 100)) { 之后执行var_dump($driver[0]),是否只显示类Driver
  • 我才意识到这与驱动实体的变化无关。这是冲洗和清除。

标签: symfony doctrine-orm


【解决方案1】:

冲洗时不要清除。

if (!($number % 100)) {
        $this->em->flush();
        $this->em->clear(); <-HERE IS THE PROBLEM
        // change driver
        $driver = $drivers[rand(0, count($drivers) - 1)];
    }

仅在命令结束时调用 clear。 如果您担心内存消耗,则仅清除某些实体(在您的情况下为 $position,但您必须将它们保存在一个数组中,然后对其进行迭代并使用 $this-em->clear($位置))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多