andig
andig

Reputation: 13898

Why does Doctrine insist on persisting referenced managed entities?

According to Doctrine 2.0 docs (http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html) a

..preexisting managed entity, is ignored by the persist operation. However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities are mapped with cascade=PERSIST or cascade=ALL (see “Transitive Persistence”)."

My understanding is that cascading to referenced managed entities should lead to referenced entities being ignored by the persist operation (case 3):

Persistence by Reachability: Cascade Persist

  1. New entities in a collection marked as cascade persist will be directly persisted by Doctrine.
  2. New entities in a collection not marked as cascade persist will produce an Exception and rollback the flush() operation.
  3. Collections without new entities are skipped.

This is however not what happens. I have a managed Channel entity with 1:n Properties and Data entities. When the Channel entity is created some properties are retrieved but not modified.

When I add data and persist the entity via

$channel->addData(new Model\Data($channel, $timestamp, $value));
$em->persist();

I can see SQL for writing the new Data entities but do also see updates to the existing Properties (with the old, unchanged value).

Why does Doctrine (2.4.1) persist relationships of managed entities?

The entity definitions look like below:

class Channel extends Entity {
    /**
     * @OneToMany(targetEntity="Data", mappedBy="channel", cascade={"persist"}, orphanRemoval=true)
     * @OrderBy({"timestamp" = "ASC"})
     */
    protected $data = NULL;

    /**
     * Constructor
     */
    public function __construct($type) {
        parent::__construct($type);
        $this->data = new ArrayCollection();
    }

    /**
     * Add a new data to the database
     */
    public function addData(\Volkszaehler\Model\Data $data) {
        $this->data->add($data);
    }

    ...
}

abstract class Entity {

    /**
     * @OneToMany(targetEntity="Property", mappedBy="entity", cascade={"remove", "persist"}, orphanRemoval=true)
     * @OrderBy({"key" = "ASC"})
     */
    protected $properties = NULL;

    /**
     * Constructor
     *
     * @param string $type
     */
    public function __construct($type) {
        if (!Definition\EntityDefinition::exists($type)) {
            throw new \Exception('Unknown entity type: \'' . $type . '\'');
        }

        $this->properties = new Collections\ArrayCollection();
    }

    ...
}

Upvotes: 3

Views: 608

Answers (1)

andig
andig

Reputation: 13898

I've finally out that Doctrine does not insist on persisting referenced managed entities.

In the case described above I had however modified the related entities (changed type on some of the properties) which Doctrine, due to its === comparison when computing the change sets, did interpret as update.

There is some discussion about using the PostFlush event to prevent this, but sofar not conclusive: https://github.com/doctrine/doctrine2/pull/382#issuecomment-43421295

Upvotes: 1

Related Questions