我们的项目中存在一个奇怪的问题,其中某些教义实体没有被保存。该问题并非每次都发生,而是间歇性发生,我们也不知道是什么原因引起的。

我们保存了两个链接的实体:

$one = (new One)
    ->setValues()
    ...
;
$two = (new Two)
    ->setOne($one)
    ->setUser($user)
;
$em->persist($one);
$em->persist($two);
$em->flush();


关系/实体定义如下:

class User {
...

    /**
     * @var Two[]|Collection
     * @ORM\OneToMany(targetEntity="Two", mappedBy="user")
     */
    private $twos;
...
}

class One {
...
    /**
     * @var Two[]|Collection
     * @ORM\OneToMany(targetEntity="Two", mappedBy="one")
     */
    private $twos;
...
}

Class Two {
...
    /**
     * Note this field in the db is an auto-increment
     * @ORM\Column(name="two_id", type="integer")
     */
    private $id;
    /**
     * @var One
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="One", inversedBy="twos")
     * @ORM\JoinColumn(name="one_id", referencedColumnName="one_id")
     */
    private $one;
    /**
     * @var User
     * @ORM\Id()
     * @ORM\ManyToOne(targetEntity="User", inversedBy="twos")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
     */
    private $user;
...
}


我们没有看到任何错误,并且当在DBAL中启用调试日志记录时,我们可以看到事务开始,所有插入(包括Two)和提交的日志条目。我们无法在本地重现该问题,因此无法使用步进调试器来解决该问题。大多数情况下,两个实体都会保存,但并非每次都保存。

如果我们从ObjectManager中清除Two实体并尝试从数据库中重新加载它,则表明它确实具有ID。

$em->clear(Two::class);

$two = $twoRepository->findTwo($user, $one);
if ($two) {
    $logger->info('Two created', ['two' => $two->getId(),]);
}


现在,当出现Two未被保存的情况时,我们可以看到一个日志,该日志正在输出一个id,但是当我们检查相关的db表时,其中没有包含该id的行。

任何时候都不会引发异常,并且我们看不到任何其他可能表明有问题的日志。

我们不知道会发生什么。为实体提供自动增量但未保存的事实表明,db事务中可能存在问题。但是,据我了解,该事务将在对flush()的调用内发生,并且没有迹象表明该事务必须回滚。再加上随后的从数据库重新加载实体的调用发生在那之后,因此Doctrine必须从数据库或从其内部对象存储中检索该实体(尽管人们很清楚clear()应该意味着它必须返回到db以加载该实体)。

最佳答案

错误的警报。事实证明,我们的系统允许用户从UI中删除实体Two(但不能删除实体One)。该网站的流量相当大,并且在最初创建实体后不久,一群用户就在这样做,这使得看上去好像根本没有创建实体。

关于php - 教义实体未保存,但具有自动递增的ID,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59825029/

10-09 20:12
查看更多