如何仅在实体不存在的情况下保留关系的一端和另一端?
How to persist only one end of a relationship and the other one only if the entity doesn't exist?
我有一个 complex/nested 对象,它是根据 Zend\Form
数据自动水合创建的。现在我想用 Doctrine 2 保存它。最好的情况是在顶层只有一个 persist(...)
和一个 flush(...)
调用。但它不是这样工作的。所以现在我有以下问题:
有对象 User
和 Order
。关系是 1:n
(所以,1
User
有 n
Order
)。 User
已经存在。当 User
Joe
试图保存多个 Order
(例如它的第二个订单)时,会发生错误:
A new entity was found through the relationship '...\Order#user' that was not configured to cascade persist operations for entity: ...\User@000000003ba4559d000000005be8d831. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement '...\User#__toString()' to get a clue.
好吧,我加cascade={"persist"}
(虽然这里没意义,但不管怎样,试试看):
class Order
{
...
/**
* @var User
*
* @ORM\ManyToOne(targetEntity="User", cascade={"persist"})
*/
protected $user;
...
}
现在可以使用了,如果给定的 User
不存在:创建一个 Order
和一个 User
。
但是如果User
存在,就会出现错误:
An exception occurred while executing 'INSERT INTO user (username, role, created, updated) VALUES (?, ?, ?, ?)' with params ["myusername", "member", null, null]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'myusername' for key 'username_UNIQUE'
如何处理保存,如果 User
还不存在,则只保存它?
解决方案是在保存引用实体之前保留 User
。如果还不存在,需要先创建(persist
ed 和 flush
ed):
$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();
我有一个 complex/nested 对象,它是根据 Zend\Form
数据自动水合创建的。现在我想用 Doctrine 2 保存它。最好的情况是在顶层只有一个 persist(...)
和一个 flush(...)
调用。但它不是这样工作的。所以现在我有以下问题:
有对象 User
和 Order
。关系是 1:n
(所以,1
User
有 n
Order
)。 User
已经存在。当 User
Joe
试图保存多个 Order
(例如它的第二个订单)时,会发生错误:
A new entity was found through the relationship '...\Order#user' that was not configured to cascade persist operations for entity: ...\User@000000003ba4559d000000005be8d831. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement '...\User#__toString()' to get a clue.
好吧,我加cascade={"persist"}
(虽然这里没意义,但不管怎样,试试看):
class Order
{
...
/**
* @var User
*
* @ORM\ManyToOne(targetEntity="User", cascade={"persist"})
*/
protected $user;
...
}
现在可以使用了,如果给定的 User
不存在:创建一个 Order
和一个 User
。
但是如果User
存在,就会出现错误:
An exception occurred while executing 'INSERT INTO user (username, role, created, updated) VALUES (?, ?, ?, ?)' with params ["myusername", "member", null, null]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'myusername' for key 'username_UNIQUE'
如何处理保存,如果 User
还不存在,则只保存它?
解决方案是在保存引用实体之前保留 User
。如果还不存在,需要先创建(persist
ed 和 flush
ed):
$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();