我有一个由ZendForm
数据自动水合创建的复杂/嵌套对象。现在我想用条令2来拯救它。最好的情况是在顶层上只有一个persist(...)
和一个flush(...)
调用。但它不是这样工作的。所以现在我有以下问题:
存在对象User
和Order
。关系为1:n
(因此,1
User
具有n
Order
s)。User
已存在。当一个User
Joe
试图保存多个Order
(例如其第二阶)时,会出现错误:
通过关系找到了一个新实体"。。。\未配置为级联实体的持久化操作的订单#user':\User@000000003ba4559d000000005be8d831.要解决此问题:请对此未知实体显式调用EntityManager#persist(),或者在映射中配置cascade-persist此关联,例如@ManyToOne(..,cascade={"persist";})。如果您找不到导致问题的实体,请执行"。。。\用户#__toString()'获取线索。
好吧,我添加了cascade={"persist"}
(尽管在这里没有意义,但无论如何,只是为了尝试一下):
class Order
{
...
/**
* @var User
*
* @ORMManyToOne(targetEntity="User", cascade={"persist"})
*/
protected $user;
...
}
现在,如果给定的User
不存在,它就工作了:创建了一个Order
和一个User
。
但如果User
存在,则会出现错误:
使用params["myusername","member",null,null]执行"INSERT INTO user(username,role,created,updated)VALUES(?,?,?)"时发生异常:
SQLSTATE[23000]:完整性约束冲突:1062密钥"username_UNIQUE"的条目"myusername"重复
如果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();