Doctrine & Symfony2 — нарушение ограничения целостности: 1062 Дублирующаяся запись «xy» для ключа «PRIMARY»


Я создаю некоторые Fixtures в Symfony2, используя Doctrine. Я получаю следующую ошибку:

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

когда я пытаюсь сохранить однонаправленную ассоциацию "многие ко многим".
Я понимаю ошибку, но я запутался: разве не очевидно, что некоторые идентификаторы дублируются в отношении "многие ко многим"?
Если я ошибаюсь, поправьте меня. Я помещаю свой код ниже, любые разъяснения приветствуются.

Файл исправления:

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();

    }
}

Объявление отношений в классе курса:

/**
     * @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();
    }

Объекты «Студент» и «Курс» также создаются с помощью Fixtures перед попыткой создать ассоциацию.
Если я попытаюсь вставить только одного студента на курс, все будет работать гладко.


person esseara    schedule 13.08.2015    source источник


Ответы (2)


Я вижу, что объекты ваших курсов уже существуют, потому что вы извлекаете их непосредственно из базы данных ($courses = $em->createQuery('SELECT c FROM sociaLecompsSuperBundle:Course c')->getResult();). Поэтому вам не следует пытаться сохранить объект во второй раз. Я предлагаю вам использовать merge() таким образом:

$em->merge($course);

Примечание 1: я вижу, что вы используете здесь фикстуры Doctrine и что учащиеся и курсы уже созданы. Если они были созданы с помощью фикстуры Doctrine, рассмотрите возможность использования методов addReference и getReference. Пример здесь: https://github.com/doctrine/data-fixtures/blob/master/README.md#sharing-objects-between-fixtures

Примечание 2. Кроме того, в вашей ассоциации subscribed_students не установлен параметр каскада. Поскольку студенты уже существуют, это не должно быть проблемой. В противном случае вы можете либо установить параметр каскада, либо запустить merge|persist также и для учащегося.

person Francesco Casula    schedule 13.08.2015
comment
Отмеченный. Спасибо за советы ^^ - person esseara; 13.08.2015

Это была самая глупая вещь.
Я заменил:

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

с участием

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

Поскольку это был пост-инкремент, вторая вставка пыталась поместить того же учащегося в базу данных, в результате чего была получена точная копия строки.

Надеюсь, это поможет кому-то.

person esseara    schedule 13.08.2015