级联不能与OneToMany一起使用

时间:2019-09-07 10:18:05

标签: php mysql symfony doctrine symfony4

我正在使用symfony 4.2.11,我需要保留一个PageTemplate实体。但是,此实体包含必须在数据库中更新的PageTemplateBlock实体。 PageTemplateBlock实体包含必须也必须更新的PageTemplateBlockProfiled,PageTemplateBlockView和PageBlockItemVersion实体。

起初,除了PageBockItemVersion实体已通过级联删除外,其他所有东西都工作正常。 所以,我试图让我的PageBlockItemVersion的列表保持不变(它很脏)..

在这里,我为SQL完整性约束而苦恼……Doctrine正确删除了我的实体,但是它在PageTemplate之前插入了PageTemplateBlock-'

结果:

SQL queries

Error message

PageTemplate

<?php

/**
 * @var int
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @var string
 * @ORM\Column(type="string")
 */
private $name;

/**
 * @var string|null
 * @ORM\Column(type="string", nullable=true)
 */
private $description;

/**
 * @var Site
 * @ORM\ManyToOne(targetEntity="Site", inversedBy="pageTemplates")
 */
private $site;

/**
 * @var PageTemplateBlock[]|ArrayCollection
 * @ORM\OneToMany(targetEntity="PageTemplateBlock", mappedBy="template", cascade={"remove", "persist"}, orphanRemoval=true)
 * @ORM\OrderBy({"order"="ASC"})
 */
private $blocks;

/**
 * @var PageVersion[]|ArrayCollection
 * @ORM\OneToMany(targetEntity="PageVersion", mappedBy="pageTemplate", cascade={"remove", "persist"}, orphanRemoval=true)
 */
private $pageVersions;

PageTemplateBlock

<?php

/**
 * @var int
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @var PageTemplate
 * @ORM\ManyToOne(targetEntity="PageTemplate", inversedBy="blocks")
 */
private $template;

/**
 * @var integer
 * @ORM\Column(type="integer", name="_order")
 */
private $order;

/**
 * @var string
 * @ORM\Column(type="string")
 */
private $name;

/**
 * @var string|null
 * @ORM\Column(type="string", nullable=true)
 */
private $description;

/**
 * @var PageTemplateBlockProfiled[]|ArrayCollection
 * @ORM\OneToMany(targetEntity="PageTemplateBlockProfiled", mappedBy="block", cascade={"remove", "persist"}, orphanRemoval=true)
 */
private $profiledData;

/**
 * @var PageTemplateBlockView[]|ArrayCollection
 * @ORM\OneToMany(targetEntity="PageTemplateBlockView", mappedBy="block", cascade={"remove", "persist"}, orphanRemoval=true)
 */
private $views;

/**
 * @var PageBlockItemVersion[]|ArrayCollection
 * @ORM\OneToMany(targetEntity="PageBlockItemVersion", mappedBy="pageTemplateBlock", cascade={"remove", "persist"}, orphanRemoval=true, fetch="EAGER")
 */
private $pageItems;

PageTemplateBlockProfiled

<?php

/**
 * @var int
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @var PageTemplateBlock
 * @ORM\ManyToOne(targetEntity="PageTemplateBlock", inversedBy="profiledData")
 * @ORM\JoinColumn(name="block_id", referencedColumnName="id", onDelete="CASCADE")
 */
private $block;

/**
 * @var Profile
 * @ORM\ManyToOne(targetEntity="Profile", inversedBy="profiledItems")
 */
private $profile;

/**
 * @var string|null
 * @ORM\Column(type="string", nullable=true)
 */
private $node;

PageTemplateBlockView

<?php

/**
 * @var int
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @var PageTemplateBlock
 * @ORM\ManyToOne(targetEntity="PageTemplateBlock", inversedBy="views")
 * @ORM\JoinColumn(name="block_id", referencedColumnName="id", onDelete="CASCADE")
 */
private $block;

/**
 * @var View
 * @ORM\ManyToOne(targetEntity="View", inversedBy="pageTemplateBlock")
 */
private $view;

/**
 * @var integer
 * @ORM\Column(type="integer", name="_order")
 */
private $order;

/**
 * @var bool
 * @ORM\Column(type="boolean")
 */
private $locked;

/**
 * @var array|null
 * @ORM\Column(type="array", nullable=true)
 */
private $data;

PageBlockItemVersion

<?php

/**
 * @var int
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

/**
 * @var PageVersion
 * @ORM\ManyToOne(targetEntity="PageVersion", inversedBy="items")
 */
private $pageVersion;

/**
 * @var PageTemplateBlock
 * @ORM\ManyToOne(targetEntity="PageTemplateBlock", inversedBy="pageVersions")
 * @ORM\JoinColumn(name="page_template_block_id", referencedColumnName="id", onDelete="CASCADE")
 */
private $pageTemplateBlock;

/**
 * @var int
 * @ORM\Column(type="integer", name="_order")
 */
private $order;

/**
 * @var array
 * @ORM\Column(type="array")
 */
private $data;

/**
 * @var View
 * @ORM\ManyToOne(targetEntity="View", inversedBy="pageBlockItems")
 */
private $view;

1 个答案:

答案 0 :(得分:0)

据我所知,您正在做太多的级联操作。

  

级联操作在内存中执行。这意味着将要执行级联操作时,将集合和相关实体提取到内存中(即使它们被标记为惰性)。这种方法允许为每个操作执行实体生命周期事件。

     

但是,在级联中将对象图拉入内存可能会导致相当大的性能开销,尤其是当级联的集合很大时。确保权衡您定义的每个级联操作的优点和缺点。

     

要使数据库级联操作依赖于删除操作而非,您可以使用onDelete选项配置每个联接列。

     

(重点:我的,来源:https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/working-with-associations.html

据我所知,您正在删除BlockView(其中block_id=409,来自屏幕快照),其中引用了一个块(id = 409),该块在以下位置被删除同时,因为您用block标记了onDelete="CASCADE"连接列。然后,您尝试为该块(BlockView)插入block_id=409,该块不再存在,因此会导致外键错误。

引用的文档说,级联在内存中执行。我会坚持这一点,只是删除连接列上的onDelete选项,因为它似乎足以使学说混淆...无论如何,请坚持一种级联方法。对于所有事件以及总体的一致性和完整性,我更喜欢使用学说方法。