PersistentCollection::clear() modifies uow for DEFERRED_EXPLICIT change tracking policy #6259

Closed
opened 2026-01-22 15:29:42 +01:00 by admin · 1 comment
Owner

Originally created by @paxal on GitHub (Jun 25, 2019).

Originally assigned to: @lcobucci on GitHub.

Bug Report

Q A
BC Break no
Version 2.6.3

Summary

Calling clear() on a Many-to-many association collection should not modify uow as long as persist() is not called on owner.
This is not the same behavior as calling removeElement() on each element, which sounds weird.

Current behavior

Calling clear() generates a DELETE FROM table WHERE owner_id = ? statement on a flush().

How to reproduce

Mapping :

<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
    <entity name="Foo"
            change-tracking-policy="DEFERRED_EXPLICIT">
        <id name="id" type="integer" column="id">
            <generator strategy="IDENTITY"/>
        </id>
        <many-to-many field="bars" target-entity="Bar">
            <cascade>
                <cascade-all/>
            </cascade>
            <join-table name="foo_bar">
                <join-columns>
                    <join-column name="foo_id" nullable="false"/>
                </join-columns>
                <inverse-join-columns>
                    <join-column name="bar_id" nullable="false"/>
                </inverse-join-columns>
            </join-table>
        </many-to-many>
    </entity>
    <entity name="Bar"
            change-tracking-policy="DEFERRED_EXPLICIT">
        <id name="id" type="integer" column="id">
            <generator strategy="IDENTITY"/>
        </id>
    </entity>
</doctrine-mapping>

with PHP code :


class Bar { public $id; }
class Foo {
    public $id;
    public $bars;
    public function __construct()
    {
        $this->bars = new ArrayCollection();
    }
}

// Create new entity
$foo = new Foo();
// Attach Bar
$foo->bars->add(new Bar());
// Persist the whole thing
$em->persist($foo);
$em->flush();
// Retrieve assigned id
$fooId = $foo->id;
// Clear em
$em->clear();

// Fetch from DB
$foo = $em->find(Foo::class, $fooId);
// Clear bars item per item
foreach ($foo->bars as $bar) {
    $foo->bars->removeElement($bar);
}
// Does nothing as $foo is not persisted
$em->flush();

$foo->bars->clear();
// Removes all elements even though $foo is not persisted
$em->flush();

Expected behavior

No statement should be executed.

Originally created by @paxal on GitHub (Jun 25, 2019). Originally assigned to: @lcobucci on GitHub. ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 2.6.3 #### Summary Calling `clear()` on a Many-to-many association collection should not modify uow as long as `persist()` is not called on owner. This is not the same behavior as calling `removeElement()` on each element, which sounds weird. #### Current behavior Calling `clear()` generates a `DELETE FROM table WHERE owner_id = ?` statement on a `flush()`. #### How to reproduce Mapping : ```xml <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"> <entity name="Foo" change-tracking-policy="DEFERRED_EXPLICIT"> <id name="id" type="integer" column="id"> <generator strategy="IDENTITY"/> </id> <many-to-many field="bars" target-entity="Bar"> <cascade> <cascade-all/> </cascade> <join-table name="foo_bar"> <join-columns> <join-column name="foo_id" nullable="false"/> </join-columns> <inverse-join-columns> <join-column name="bar_id" nullable="false"/> </inverse-join-columns> </join-table> </many-to-many> </entity> <entity name="Bar" change-tracking-policy="DEFERRED_EXPLICIT"> <id name="id" type="integer" column="id"> <generator strategy="IDENTITY"/> </id> </entity> </doctrine-mapping> ``` with PHP code : ```php class Bar { public $id; } class Foo { public $id; public $bars; public function __construct() { $this->bars = new ArrayCollection(); } } // Create new entity $foo = new Foo(); // Attach Bar $foo->bars->add(new Bar()); // Persist the whole thing $em->persist($foo); $em->flush(); // Retrieve assigned id $fooId = $foo->id; // Clear em $em->clear(); // Fetch from DB $foo = $em->find(Foo::class, $fooId); // Clear bars item per item foreach ($foo->bars as $bar) { $foo->bars->removeElement($bar); } // Does nothing as $foo is not persisted $em->flush(); $foo->bars->clear(); // Removes all elements even though $foo is not persisted $em->flush(); ``` #### Expected behavior No statement should be executed.
admin added the Bug label 2026-01-22 15:29:42 +01:00
admin closed this issue 2026-01-22 15:29:43 +01:00
Author
Owner

@lcobucci commented on GitHub (Oct 2, 2019):

Handled by #7761

@lcobucci commented on GitHub (Oct 2, 2019): Handled by #7761
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6259