doctrine / orm

Doctrine Object Relational Mapper (ORM)
https://www.doctrine-project.org/projects/orm.html
MIT License
9.94k stars 2.51k forks source link

DDC-1879: Orphans are neither nulled nor removed when merging a graph of detached entities #2542

Open doctrinebot opened 12 years ago

doctrinebot commented 12 years ago

Jira issue originally created by user systho:

When merging a graph of detached entities, the created entitied are created and the updated entities are updated but the non-present entities (which exist in the database but are not in the graph) are neither removed nor have them their association column nullified.

Example :

In my code I have 2 entities : Parent and Child. There is a OneToMany(cascade={"all"}, orphanRemoval=true) relation defined in Parent.

In my database I have a Parent row with an id of 1, which has 3 Children with ids 1,2,3.

When I write the following code, I expect the Parent with id 1 and the Child with id 2 to be updated, a new Child to be created and the Child with id 1 and 3 to be deleted.

$parent = new Parent(); $parent->id = 1  // detached entity
$existing_child = new Child(); $child->id = 2 // detached entity
$new_child = new Child(); // new entity
$dinner->addChild($existing_child);
$dinner->addChild($new_child);

$em->merge($dinner);

$em->flush();

The objects I expect to be created and updated have the correct behaviour but the old children are not touched, they are still present in the database.

doctrinebot commented 11 years ago

Comment created by @ocramius:

I don't think this is valid. Orphan removal scheduling is handled only when an unit of work is available.

What's the state of $dinner before your example? Can you var_dump it?

MatthiasKuehneEllerhold commented 6 years ago

@Ocramius I've ran into the same problem today. So I guess this issue is still relevant?

I guess $dinner was meant to be $parent in systho example? $parent has ID 1 and an ArrayCollection (I guess?) with just the two childs:

Our expections are:

What I've tried:

$dbParent = $em->getRepository(..)->find(1);
echo $dbParent->getChildren()->count(); // echos '3'

echo $parent->getChildren()->count(); // echos '2'
$newDbParent = $em->merge($parent);
$em->flush();

echo $newDbParent->getChildren()->count(); // echos '2' as expected

But the obsolete children were never deleted from the database. I hooked up an SQL query logger to doctrine and there are only UPDATE & INSERT queries in it, the DELETE queries are missing.

Mapping annotation of $children in class Parent:

    /**
     * @var Child[]|ArrayCollection
     * @ORM\OneToMany(
     *     targetEntity="Child",
     *     mappedBy="parent",
     *     cascade={"all"},
     *     orphanRemoval=true,
     *     fetch="EAGER"
     * )
     */
    protected $children;

Mapping annotation of $parent in class Child:

    /**
     * @var Parent
     * @ORM\ManyToOne(targetEntity="Parent", inversedBy="children", cascade={"all"})
     * @ORM\JoinColumn(name="parent", referencedColumnName="id", nullable=false)
     */
    protected $parent;

I'm using doctrine/orm in a zend-expressive project with these versions:

dasprid/container-interop-doctrine       1.0.0             
doctrine/annotations                     v1.5.0            
doctrine/cache                           v1.7.1            
doctrine/collections                     v1.5.0            
doctrine/common                          v2.8.1            
doctrine/dbal                            v2.6.2            
doctrine/inflector                       v1.2.0            
doctrine/instantiator                    1.1.0             
doctrine/lexer                           v1.0.1            
doctrine/orm                             v2.5.12 
lcobucci commented 6 years ago

@MatthiasKuehneEllerhold could you please send us a failing test case that reproduces that behaviour? It would help us a lot to identify and fix the issue you're describing.

You can find examples on https://github.com/doctrine/doctrine2/tree/388afb46d0cb3ed0c51332e8df0de9e942c2690b/tests/Doctrine/Tests/ORM/Functional/Ticket

MatthiasKuehneEllerhold commented 6 years ago

I've opened a PR with a failing test case for this: https://github.com/doctrine/doctrine2/pull/6850 .

Liiva commented 5 years ago

I'm running into the same issue. In the PR it is mentioned this might be fixed in version 2.6 but as we're using 2.7.1 I assume this is not the case. Any updates on this issue?

I've created a separate repo with a reproducible case here.