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 重复条目的主要内容,如果未能解决你的问题,请参考以下文章

原则 3:一对一的单向关系不会返回所有字段

如何通过学说实体之间的 ID 建立一对一的关系

Doctrine 对一对多关系进行了许多查询

更新数据库中的表/字段 - Doctrine 2 和 Codeigniter 2

如何使用 Doctrine 选择没有具有特定值的一对多实体的所有行

使用 Doctrine ORM (1.2) 为预先存在的记录创建一对一关系