如果实体不存在,如何只保留一个关系的一端而另一端只保留?

问题描述 投票:0回答:1

我有一个复杂/嵌套的对象,通过Zend\Form数据的自动水合作用创建。现在我想用Doctrine 2保存它。最好的情况是只有一个persist(...)和一个flush(...)呼叫在顶层。但它不会像这样工作。所以现在我有以下问题:

有对象UserOrder。这种关系是1:n(因此,1 Usern Orders)。 User已经存在。当User Joe试图保存多个Order(例如它的第二个订单)时,会发生错误:

通过“...#Order#user”关系找到了一个新实体,该关系未配置为对实体进行级联持久操作:... \ User @ 000000003ba4559d000000005be8d831。要解决此问题:在此未知实体上显式调用EntityManager#persist()或在映射中配置级联持久保存此关联,例如@ManyToOne(..,cascade = {“persist”})。如果你无法找出哪个实体导致问题实现'... \ User #__ toString()'得到一个线索。

好吧,我添加了cascade={"persist"}(虽然这里没有意义,但无论如何,只是为了尝试一下):

class Order
{
    ...
    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="User", cascade={"persist"})
     */
    protected $user;
    ...
}

现在它有效,如果给定的User不存在:创建了OrderUser

但如果User存在,则会发生错误:

使用params [“myusername”,“member”,null,null]执行'INSERT INTO用户(用户名,角色,创建,更新)VALUES(?,?,?,?)'时发生异常:

SQLSTATE [23000]:完整性约束违规:1062重复条目'username_UNIQUE'的重复条目'myusername'

如何处理保存所以,User只保存,如果它还不存在?

doctrine-orm doctrine one-to-many many-to-one persist
1个回答
0
投票

解决方案是在保存引用实体之前保留User。如果它还不存在,则需要先创建(persisted和flushed):

$user = $this->entityManager->getRepository(User::class)->findOneBy(
    ['username' => $dataObject->getUser()->getUsername()]
);
if (! $user) {
    $this->entityManager->persist($dataObject->getUser());
    $this->entityManager->flush($dataObject->getUser());
    $user = $this->entityManager->getRepository(User::class)->findOneBy(
        ['username' => $dataObject->getUser()->getUsername()]
    );
}
$dataObject->setUser($user);

$this->entityManager->persist($dataObject);
$this->entityManager->flush();

并且不应该使用cascade={"persist"},因为在这种情况下它实际上没有意义。


编辑

甚至更容易:

$user = $this->entityManager->getRepository(User::class)->findOneBy(
    ['username' => $dataObject->getUser()->getUsername()]
);
if ($user) {
    $dataObject->setUser($user);
} else {
    $this->entityManager->persist($dataObject->getUser());
}

$this->entityManager->persist($dataObject);
$this->entityManager->flush();
© www.soinside.com 2019 - 2024. All rights reserved.