完整性约束违规,外键约束失败

时间:2014-09-15 14:01:12

标签: symfony doctrine-orm foreign-keys constraints entity-relationship

我有3个实体:Invoice,InvoiceItemService,Asset。

首先,我创建一个Invoice和一个InvoiceItemService,并在InvoiceItemService端将它们与ManyToOne关系链接在一起(因此InvoiceItemService是所有者方)。

然后,我可以从Invoice对象创建一个Asset。资产是发票的副本,总数为负数。当我创建一个Asset时,我也将Invoice的InvoiceItemService链接到Asset,并在InvoiceItemService和Asset之间建立了ManyToOne关系。

当我删除发票时,一切正常,Invoice,Asset和InvoiceItemService会被cascade = {“remove”}选项删除。

当我删除资产时,我希望只删除资产。但是我得到了这个外键错误。

以下是我的实体:

class Invoice
{
    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\Asset", mappedBy="invoice", cascade={"remove"})
     */
    protected $assets;

    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\InvoiceItemService", mappedBy="invoice", cascade={"persist", "remove"})
     */
    protected $services;
}

class Asset
{
    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Invoice", inversedBy="assets")
     * @ORM\JoinColumn(nullable=false)
     * @Exclude
     */
    protected $invoice;

    /**
     * @ORM\OneToMany(targetEntity="Evo\BackendBundle\Entity\InvoiceItemService", mappedBy="asset")
     */
    protected $services;
}

class InvoiceItemService extends InvoiceItem
{
    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Invoice", inversedBy="services")
     * @ORM\JoinColumn(nullable=false, onDelete="CASCADE")
     * @Type("Evo\BackendBundle\Entity\Invoice")
     * @Exclude
     */
    protected $invoice;

    /**
     * @ORM\ManyToOne(targetEntity="Evo\BackendBundle\Entity\Asset", inversedBy="services")
     * @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
     * @Type("Evo\BackendBundle\Entity\Asset")
     * @Exclude
     */
    protected $asset;
}

1 个答案:

答案 0 :(得分:1)

正如Cerad在上述评论中提到的那样,您需要自己实施此行为。

由于您需要访问实体管理器,因此您无法通过Asset实体本身的简单生命周期回调来执行此操作。相反,您需要注册服务以侦听事件并在此时执行操作。

示例实现

应用/ config.yml

services:
    your.bundle.association.manager:
        class: Your\Bundle\Model\AssociationManager
        tags:
            - { name: doctrine.event_listener, event: preRemove }

然后,服务类本身(未经测试 - 可能有错误)

namespace Your\Bundle\Model;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManager;
use Your\Bundle\Entity\Asset;

class AssociationManager
{
  public function preRemove(LifecycleEventArgs $args)
  {
    if ($entity instanceof Asset)
    {
      $this->removeAssetAssociations($asset, $args->getEntityManager());
      return;
    }
  }

  protected function removeAssetAssociations(Asset $asset, EntityManager $em)
  {
    foreach ($asset->getServices() as $invoiceItemService)
    {
      $invoiceItemService->asset = null;
      $em->persist($invoiceItemService);
    }
  }
}

希望这有帮助。