esseara
esseara

Reputation: 880

Doctrine & Symfony2 - Integrity constraint violation: 1062 Duplicate entry 'x-y' for key 'PRIMARY


I am creating some Fixtures in Symfony2 using Doctrine. I get the following error:

Integrity constraint violation: 1062 Duplicate entry '206-411' for key 'PRIMARY'

when I try to persist a many-to-many unidirectional association.
I understand the error, but I'm confused: isn't obvious that some IDs are duplicate in a many-to-many relationship?
If I'm wrong please correct me. I put my code below, any clarification is welcome.

Fixture file:

namespace sociaLecomps\SuperBundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\Query;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;


class LoadAssociationsData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
    private $container;

    public function setContainer(ContainerInterface $container = null){
        $this->container = $container;
    }

    public function load(ObjectManager $manager)
    {
        $em = $this->container->get('doctrine')->getManager('default');

        /*
         * COURSE - STUDENT ASSOCIATION
         */

        $courses = $em->createQuery('SELECT c FROM sociaLecompsSuperBundle:Course c')->getResult();
        $students = $em->createQuery('SELECT s FROM sociaLecompsSuperBundle:Student s')->getResult();

        $i=0;
        for($j=0; $j<count($courses); $j++){

            $course = $courses[$j];

            //here I'm adding two different students to the same course
            $s = array($students[$i], $students[$i++]);
            $course->setSubscribedStudents($s);
            $em->persist($course);

            $i++;
        }
        $manager->flush();

    }
}

Relationship declaration in Course class:

/**
     * @ORM\ManyToMany(targetEntity="Student")
     * @ORM\JoinTable(name="relation_course_student",
     *      joinColumns={@ORM\JoinColumn(name="course_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="student_id", referencedColumnName="id")}
     *      )
     **/
    private $subscribed_students;

    public function __construct() {
        $this->subscribed_students = new ArrayCollection();
    }

Entities Student and Course are created, also with Fixtures, before attempting to create the association.
If I try to insert only one student per course it all works smoothly.

Upvotes: 3

Views: 6303

Answers (2)

esseara
esseara

Reputation: 880

That was the stupidest thing.
I replaced:

$s = array($students[$i], $students[$i++]);

with

$s = array($students[$i], $students[++$i]);

Since it was a post-increment, the second insertion tried to put the same student into the database, resulting with an exact row duplicate.

Hope this helps someone.

Upvotes: 1

Francesco Casula
Francesco Casula

Reputation: 27120

I see that your courses entities already exist because you're fetching them directly from the database ($courses = $em->createQuery('SELECT c FROM sociaLecompsSuperBundle:Course c')->getResult();). So you shouldn't be trying to persist the entity a second time. I suggest you use merge() this way:

$em->merge($course);

Note 1: I see you're using Doctrine fixtures here and that students and courses have already been created. If they have been created through a Doctrine fixture as well consider using the addReference and getReference methods. Example here: https://github.com/doctrine/data-fixtures/blob/master/README.md#sharing-objects-between-fixtures

Note 2: Also you don't have a cascade option set into your subscribed_students association. Since the students already exist should not be an issue. Otherwise you can either set the cascade option or run a merge|persist on the student entity as well.

Upvotes: 2

Related Questions