DDC-978: Many-To-Many relations are removed after Flush() #1217

Closed
opened 2026-01-22 13:06:18 +01:00 by admin · 5 comments
Owner

Originally created by @doctrinebot on GitHub (Jan 12, 2011).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user slasher:

Let's say we have three entities: User, Channel, and Log

Every time a User is created or updated, Channels are assigned to a Many-To-Many collection.
This action gets logged in the Log entity.

I have reproduced the bug in the Doctrine sandbox (see attachment). It's a fully working example.
This is a summary:

// Fetch two channels in an array
$channels = .......

// create a new user and assign channels
$user = new User();
$user->setName('FooBar');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
// Fetch two channels in an array
$channels = .......

// fetch an existing user, **change something to the user**, and assign channels
$user = .............
$user->setName('Gaz');
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

$em->persist($log);
$em->flush();
// Fetch two channels in an array
$channels = .......

// fetch an existing user and only assign channels, change nothing else
$user = .............
$user->setChannels($channels);

//save the user
$em->persist($user);
$em->flush();

// log it
$log = new Log();
$log->setMessage('User created with two channels');
$log->setItem($user);

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

This last piece of code generates following SQL code (summarized):

DELETE FROM user_channels WHERE userId = 1
INSERT INTO user_channels (userId, channelId) VALUES (1, 2);
DELETE FROM user_channels WHERE userId = 1

If you remove the $em->flush() after $em->persist($user); in the last example, the code works (channels are persisted).

I did not have this problem with Doctrine2 Alpha4.

Originally created by @doctrinebot on GitHub (Jan 12, 2011). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user slasher: Let's say we have three entities: User, Channel, and Log Every time a User is created or updated, Channels are assigned to a Many-To-Many collection. This action gets logged in the Log entity. I have reproduced the bug in the Doctrine sandbox (see attachment). It's a fully working example. This is a summary: ``` // Fetch two channels in an array $channels = ....... // create a new user and assign channels $user = new User(); $user->setName('FooBar'); $user->setChannels($channels); //save the user $em->persist($user); $em->flush(); // log it $log = new Log(); $log->setMessage('User created with two channels'); $log->setItem($user); $em->persist($log); $em->flush(); ``` ``` // Fetch two channels in an array $channels = ....... // fetch an existing user, **change something to the user**, and assign channels $user = ............. $user->setName('Gaz'); $user->setChannels($channels); //save the user $em->persist($user); $em->flush(); // log it $log = new Log(); $log->setMessage('User created with two channels'); $log->setItem($user); $em->persist($log); $em->flush(); ``` ``` // Fetch two channels in an array $channels = ....... // fetch an existing user and only assign channels, change nothing else $user = ............. $user->setChannels($channels); //save the user $em->persist($user); $em->flush(); // log it $log = new Log(); $log->setMessage('User created with two channels'); $log->setItem($user); $em->persist($log); $em->flush(); ``` This last piece of code generates following SQL code (summarized): ``` DELETE FROM user_channels WHERE userId = 1 INSERT INTO user_channels (userId, channelId) VALUES (1, 2); DELETE FROM user_channels WHERE userId = 1 ``` If you remove the _$em->flush()_ after _$em->persist($user);_ in the last example, the code works (channels are persisted). I did not have this problem with Doctrine2 Alpha4.
admin added the Bug label 2026-01-22 13:06:18 +01:00
admin closed this issue 2026-01-22 13:06:19 +01:00
Author
Owner

@doctrinebot commented on GitHub (Jan 12, 2011):

@doctrinebot commented on GitHub (Jan 12, 2011): - is duplicated by [DDC-983: Creating new collection for manyToMany results in loss of data with multiple flushes](http://www.doctrine-project.org/jira/browse/DDC-983)
Author
Owner

@doctrinebot commented on GitHub (Jan 12, 2011):

Comment created by @beberlei:

What do you do in "setChannels"? Do you completly overwrite the previous content of the association variable "User::$channels" ?

@doctrinebot commented on GitHub (Jan 12, 2011): Comment created by @beberlei: What do you do in "setChannels"? Do you completly overwrite the previous content of the association variable "User::$channels" ?
Author
Owner

@doctrinebot commented on GitHub (Jan 12, 2011):

Comment created by slasher:

I have reproduced the bug in a fully working example. See attachment. Just read instructions in comment and execute each step seperately.

But yes, I overwrite the previous content of the association variable "User::$channels" with a Doctrine ArrayCollection.
\

/*** @Entity @Table(name="users") **/
class User
{
    /****
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;
    /*** @Column(type="string", length=50) **/
    private $name;

    /****
     * @ManyToMany(targetEntity="Channel")
     * @JoinTable(name="users_channels",
     *          joinColumns={@JoinColumn(name="userId",
                referencedColumnName="id")},
     *          inverseJoinColumns={@JoinColumn(name="channelId",
     *          referencedColumnName="id")}
     *      )
     * @var ArrayCollection
     */
    protected $channels;

    public function **construct(){
        $this->channels = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function getId()
    {
        return $this->id;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setName($name)
    {
        $this->name = $name;
    }

    public function getChannels() {
        return $this->channels;
    }

    public function setChannels($channels) {
        $channels =  new \Doctrine\Common\Collections\ArrayCollection($channels);

        $this->channels = $channels;
    }
}
@doctrinebot commented on GitHub (Jan 12, 2011): Comment created by slasher: I have reproduced the bug in a fully working example. See attachment. Just read instructions in comment and execute each step seperately. But yes, I overwrite the previous content of the association variable "User::$channels" with a Doctrine ArrayCollection. \ ``` /*** @Entity @Table(name="users") **/ class User { /**** * @Id @Column(type="integer") * @GeneratedValue(strategy="AUTO") */ private $id; /*** @Column(type="string", length=50) **/ private $name; /**** * @ManyToMany(targetEntity="Channel") * @JoinTable(name="users_channels", * joinColumns={@JoinColumn(name="userId", referencedColumnName="id")}, * inverseJoinColumns={@JoinColumn(name="channelId", * referencedColumnName="id")} * ) * @var ArrayCollection */ protected $channels; public function **construct(){ $this->channels = new \Doctrine\Common\Collections\ArrayCollection(); } public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function getChannels() { return $this->channels; } public function setChannels($channels) { $channels = new \Doctrine\Common\Collections\ArrayCollection($channels); $this->channels = $channels; } } ```
Author
Owner

@doctrinebot commented on GitHub (Jan 23, 2011):

Comment created by @beberlei:

Fixed.

@doctrinebot commented on GitHub (Jan 23, 2011): Comment created by @beberlei: Fixed.
Author
Owner

@doctrinebot commented on GitHub (Jan 23, 2011):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Jan 23, 2011): Issue was closed with resolution "Fixed"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1217