如何只保留关系的一端,而仅在实体不存在时才保留另一端?



我有一个由ZendForm数据自动水合创建的复杂/嵌套对象。现在我想用条令2来拯救它。最好的情况是在顶层上只有一个persist(...)和一个flush(...)调用。但它不是这样工作的。所以现在我有以下问题:

存在对象UserOrder。关系为1:n(因此,1User具有nOrders)。User已存在。当一个UserJoe试图保存多个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。如果它还不存在,则需要首先创建(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();

相关内容

最新更新