ORM Doctrine 中的 ManyToOne on update CASCADE(Symfony)

13

我有两个实体

class Promotor
{

/**
 * @ORM\ManyToOne(targetEntity="Ciudad", inversedBy="promotor")
 * @ORM\JoinColumn(name="ciudad_id", referencedColumnName="id", nullable=false)
 */
protected $ciudad;

class Ciudad
{
/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

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

一个"Promotor"可以居住在一个"Ciudad"(城市)中。一个"Ciudad"(城市)中可以居住许多"Promotores"。

如果我在JoinColumn中添加onDelete="CASCADE"

/**
 * @ORM\ManyToOne(targetEntity="Ciudad", inversedBy="promotor")
 * @ORM\JoinColumn(name="ciudad_id", referencedColumnName="id", nullable=false, onDelete="CASCADE")
 */
protected $ciudad;

它产生下一个代码。

ALTER TABLE promotor DROP FOREIGN KEY FK_BF20A37FE8608214;
ALTER TABLE promotor ADD CONSTRAINT FK_BF20A37FE8608214 FOREIGN KEY (ciudad_id)
REFERENCES Ciudad (id) ON DELETE CASCADE

但我也喜欢在更新时进行级联操作。我尝试使用 onUpdate="CASCADE" ,但它不起作用。

[Doctrine\Common\Annotations\AnnotationException]
[Creation Error] The annotation @ORM\JoinColumn declared on property     Web\PromotorBundle\Entity\Promotor::$ciudad does not have a property named
"onUpdate". Available properties: name, referencedColumnName, unique, nulla
ble, onDelete, columnDefinition, fieldName

我理解这个错误表示onUpdate属性不存在,但是.. 有没有办法在更新时进行级联操作?


1
我在Doctrine的文档中找到了这个注释,但我不理解。在更新时控制级联已不再必要。理论上它永远不会改变ID。 - JGrinon
1个回答

16

onDelete="CASCADE" 在数据库层面上使用。正如您所说,没有 onUpdate。另一个缺点是 ON DELETE CASCADE 只适用于 InnoDB。它不适用于 MyISAM。

但是您可以使用 Doctrine 内存级联操作:

class Promotor
{

/**
* @ORM\ManyToOne(targetEntity="Ciudad", inversedBy="promotor", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="ciudad_id", referencedColumnName="id", nullable=false)
*/
protected $ciudad;

所有的内容都在文档中有详细描述:https://www.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations

此外,你也可以跳过JoinColumn注释,因为按照你所写的方式,这是默认配置并且会被隐式生成。

因此,你只需要写:

class Promotor
{

/**
* @ORM\ManyToOne(targetEntity="Ciudad", inversedBy="promotor", cascade={"persist", "remove"})
*/
protected $ciudad;

顺便问一下,如果“Ciudad”实体没有“$promotor”字段,为什么在“$ciudad”属性上会有“inversedBy =”promotor“”?(而且从MTO关系的性质来看,它根本不能有对“Promotor”的'反向'引用)。 - Dimitry K
你是对的,Ciudad实体上没有promotor属性。因此,就不能有inversedBy="promotor"。 但是,你关于ManyToOne关系和inverse引用的错误。ManyToOne具有inverse,OneToMany具有mappedBy - alsar
抱歉,我的措辞不够精确。当我说“反转”时,实际上指的是相同的 inversedBy。尽管您所说的看起来很合乎逻辑(不能有“inversedBy =“promotor””),但我查阅了 @ManyToOne 的文档 http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html#annref-manytoone 并提到了这个 inversedBy 参数(虽然不是必须的)。但我仍然感到困惑 - MTO 关系怎么可能有 inversedBy 呢?难道不是真的吗,如果有 inversedBy,就会变成 ManyToMany 关系? - Dimitry K
2
我想我弄清楚了:根据文档,“inversedBy”属性指定实体中作为关系反向方的字段。关键词是“实体中的字段” - 它是另一个实体中的字段(但在数据库中的其他实体表示中,不会为该关系添加额外的字段)。它仍然是MTO到OTM的关系。 - Dimitry K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接