Doctrine “A new entity was found through the relat

2019-02-16 14:47发布

First off I want to say I've read through all the docs and googled this plenty before posting this question. I know what that error means (un-persisted entity in a relationship)

I'm getting this error where I think I shouldn't be getting it.

I have a OneToMany Bi-Directional relationship as follow:

Class Channel
{
    /** 
    * @ORM\OneToMany(targetEntity="Step", mappedBy="channel", cascade={"all"}, orphanRemoval=true)
    * @ORM\OrderBy({"sequence" = "ASC"})
    */
    protected $steps;
}

Class Step
{
    /** 
    * @ORM\ManyToOne(targetEntity="Channel", inversedBy="steps")
    */
    protected $channel;
}

One Channel can have many Steps and the owning side is Channel. After I upgraded from Doctrine 2.4 to 2.5 I'm getting this error:

Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship 'Company\MyBundle\Entity\Step#channel' that was not configured to cascade persist operations for entity

why is it even finding new relationships from the inverse side? Here's my code:

$channel = new Channel();
$step = new Step();
$channel->addStep($step);
$em->persist($channel);
$em->flush();

Thanks!

2条回答
我想做一个坏孩纸
2楼-- · 2019-02-16 15:35

You're right: Doctrine looks only for changes into owning side but you're wrong: owning side of your relationship is Step, not Channel.

Why is step the owning side? Because is the entity that has foreign key. Even Doctrine documentation says to you

The owning side has to use the inversedBy attribute of the OneToOne, ManyToOne, or ManyToMany mapping declaration. The inversedBy attribute contains the name of the association-field on the inverse-side.

Possible solutions:

  • Try to invert cascade operations by putting cascade={"all"} into Step entity (are you sure that all is the correct choice?)

  • Persist explicitly both entities:

    $channel = new Channel();
    $step = new Step();
    $channel->addStep($step);
    $em->persist($channel);
    $em->persist($step);
    $em->flush();
    

    here you can read why second way provided here is fine too

查看更多
再贱就再见
3楼-- · 2019-02-16 15:35

You try to persist $channel, but it has Step entity inside. So in Doctrine now you have 2 entities that are queued for inserting. Then Doctrine order entities in the order where first is Step because it has channel_id foreign key (that is empty now). Doctrine try persist this entity and when it understands that channel_id is empty it sees for cascade rules for persisting. It doesn't see any cascade rules and throw you this exception.

查看更多
登录 后发表回答