级联持久性不工作(Doctrine ORM + Symfony 2)

Posted

技术标签:

【中文标题】级联持久性不工作(Doctrine ORM + Symfony 2)【英文标题】:Cascaded persist not working (Doctrine ORM + Symfony 2) 【发布时间】:2013-11-05 12:00:56 【问题描述】:

几个月前我开始使用 symfony,有一件事情一直困扰着我。当我在 Doctrine 中有一个一对多的关系并且我尝试将一些东西插入数据库时​​。这是一个例子:

Broker.orm.yml

Acme\DemoBundle\Entity\Broker:
    type: entity
    table: brokers
    repositoryClass: BrokerRepository
    id:
        id:
            type: integer
            generator:  strategy: AUTO 
    fields:
        name:
            type: string
            length: 255
        slug:
            type: string
            length: 64
    oneToMany:
        accountTypes:
            targetEntity: Acme\DemoBundle\Entity\AccountType
            mappedBy: broker
            cascade: ["persist"]

AccountType.orm.yml

Acme\DemoBundle\Entity\AccountType:
    type: entity
    table: account_types
    repositoryClass: AccountTypeRepository
    id:
        id:
            type: integer
            generator:  strategy: AUTO 
    fields:
        name:
            type: string
            length: 255
        slug:
            type: string
            length: 64
    manyToOne:
        broker:
            targetEntity: Acme\DemoBundle\Entity\Broker
            inversedBy: accountTypes
            joinColumn:
                name: broker_id
                referencedColumn: id

然后尝试像这样将其保存到数据库中。

$accountType = new AccountType();
$accountType->setName("blabla");
// additional data to accountType

$broker->addAccountType($accountType);

$em->persist($broker);
$em->flush();

奇怪的是,它只有一个小问题就可以正常工作。 Broker 已更新,AccountType 已插入数据库,但 accountType 与 Broker 没有任何关系。 换句话说,当我签入数据库时​​,broker_id 字段保持不变并包含NULL.

如果我手动添加$accountType->setBroker($broker),它可以工作。但是我开始使用 Sonata Admin Bundle,因为这样做要复杂得多,而且我真的不需要复杂的管理系统。所以我只想快速开发它,没有这个“功能”几乎是不可能的。

不管怎样,如果我向一个对象的集合添加一些东西,它应该知道哪个对象是它的父对象,对吧? :)

提前感谢您的帮助!

【问题讨论】:

在您添加 $accountType 之前,您的 Broker 对象 $broker 是否已经被理论所知(即从存储库中获取)? 如果在使用 setter 添加到 broker 之前持久化新创建的 $accountType 会发生什么? $em->persist($accountType); 这就是 cascade 选项的基本用途——他不想显式地持久化相关实体。 $broker 是学说已知的对象,从数据库中获取。 是的,我不想保留之前新创建的 accountType。这就是我想使用级联持久化的原因。 【参考方案1】:
class Broker

    public function addAccountType($accountType)
    
        $this->accountTypes[] = $accountType;

        // *** This is what you are missing ***
        $accountType->setBroker($this);

【讨论】:

谢谢!我用学说生成了实体类,我没有想到模型类中的这个小变化。 (也许在教义上有一个选择?这对我来说似乎很常见。) 还有一件事,当我像我在问题中写的那样测试它时它会起作用。但是当我向集合中添加一些东西时,它在 Sonata Admin 包中不起作用。 :((

以上是关于级联持久性不工作(Doctrine ORM + Symfony 2)的主要内容,如果未能解决你的问题,请参考以下文章

Doctrine 2 ORM 级联删除相关实体

Doctrine ORM 使用啥机制来创建“持久”对象?

Doctrine ORM:使用由外键组成的复合主键持久化集合

教义 2 OneToMany 级联设置 NULL

Zend2 框架 - 给映射异常的 Doctrine ORM

类中的教义注释“@Doctrine\ORM\Annotation\Entity”不存在或无法自动加载