Doctrine 中的一对一关系仅更新一个字段 - 违反完整性约束:1062 重复条目
Posted
技术标签:
【中文标题】Doctrine 中的一对一关系仅更新一个字段 - 违反完整性约束:1062 重复条目【英文标题】:One to One relation in Doctrine updates only one field - Integrity constraint violation: 1062 Duplicate entry 【发布时间】:2015-10-22 13:26:36 【问题描述】:这是我之前的帖子Relations while updating entity in Symfony2 - one-to-one and one-to-many doesn't work的后续内容
虽然我已经设法解决了一对多的问题,尽管通过控制器中的一些脏修复,但同样不适用于一对一,我收到以下错误: SQLSTATE[23000]:完整性约束违规:1062 键 'UNIQ_3BAE0AA753C674EE' 的重复条目 '16'
代码:
Class Offer
/**
* @var Event
*
* @ORM\OneToOne(targetEntity="Event", inversedBy="offer")
* @ORM\JoinColumn(name="event_id", referencedColumnName="id")
*/
private $event;
Class Event
/**
* @var Offer
*
* @ORM\OneToOne(targetEntity="Offer", mappedBy="event")
* @ORM\JoinColumn(name="offer_id", referencedColumnName="id", onDelete="SET NULL")
*/
private $offer;
另外,在上一篇文章中,有人建议我在 setEvent 上添加以下代码(确切地说是 "$event->setOffer($this);" 部分:
/**
* Set event
*
* @param \AppBundle\Entity\Event $event
* @return Offer
*/
public function setEvent(\AppBundle\Entity\Event $event)
$this->event = $event;
$event->setOffer($this);
return $this;
更新后,它只填充正确的数据,即 Offer 表中的 event_id,或者在修改代码后,我收到关于重复条目 SQLSTATE[23000] 的错误:完整性约束违规:1062 Duplicate entry '16' for key 'UNIQ_3BAE0AA753C674EE'
知道我做错了什么吗?如有任何反馈,我将不胜感激。
更新和解决方案(代码添加到 OfferController 中的 updateAction):
$oldEvent = $em->getRepository('AppBundle:Event')->findOneBy(array("offer"=>$entity));
if ($oldEvent != NULL)
$oldEvent->removeOffer();
$em->persist($oldEvent);
$newEvent = $entity->getEvent();
$entity->setEvent($newEvent);
不是一个干净的方式,而是一个快速修复但工作正常,但我仍然对发生的事情感兴趣,它在 ORM 原则方式中无法开箱即用。
【问题讨论】:
不确定这是否是问题,但 JoinColumn 注释应该只出现在“拥有”端(Offer
在这种情况下)
谢谢。是的,你是对的 - 提到的注释是不必要的,但是在删除它并运行学说:模式:更新后,问题仍然如上所述“SQLSTATE [23000]:完整性约束违规:(...)”我是没有什么想法可能会被破坏。
无论如何 - 它不能正常工作,所以我不得不在控制器中添加一个不太漂亮的解决方案,即:$oldEvent = $em->getRepository('AppBundle:Event')->findOneBy(array("offer"=>$entity)); if ($oldEvent != NULL) $oldEvent->removeOffer(); $em->persist($oldEvent); $newEvent = $entity->getEvent(); $entity->setEvent($newEvent);
它作为一个快速修复工作正常,在空闲时间,我会再试一次标准的 Doctrin ORM。
【参考方案1】:
In the documentation你可以读到:
Doctrine 只会检查关联的拥有方是否有更改。
还有here详细:
要完全理解这一点,请记住在对象世界中如何维护双向关联。关联的每一侧都有 2 个引用,这 2 个引用都代表相同的关联,但可以相互独立地更改。当然,在正确的应用程序中,双向关联的语义由应用程序开发人员正确维护(这是他的责任)。 Doctrine 需要知道这两个内存引用中的哪一个是应该被持久化的,哪个不是。这就是拥有/逆概念的主要用途。
您的setEvent
方法完全符合它的预期。它还处理关系的反面。
但这也意味着您必须从拥有方管理您的实体。
Offer
是关系的拥有方,所以我建议在 $offer
而不是 $event
上调用 persist。
$offer->setEvent($event);
$em->persist($offer);
【讨论】:
以上是关于Doctrine 中的一对一关系仅更新一个字段 - 违反完整性约束:1062 重复条目的主要内容,如果未能解决你的问题,请参考以下文章
更新数据库中的表/字段 - Doctrine 2 和 Codeigniter 2