Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-2244

One-To-Many Cascade saving not working properly

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Invalid
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: ORM
    • Labels:
      None

      Description

      I have the following code:

      $new = new InterviewReview();
      
      $question = new InterviewReviewQuestion();
      $new->addQuestion($question);
      
      $em->persist($new);
      $em->flush();
      

      When i execute this code i have the following error:

      An exception occurred while executing 'INSERT INTO interview_review_question (question, tags, created_at, interview_review_id) VALUES (?, ?, ?, ?)' with params {"1":"asdfg","2":"asdfg","3":null,"4":null}:
      
      Column 'interview_review_id' cannot be null
      

      Here are my entities:

      /**
       * InterviewReview
       *
       * @ORM\Table(name="interview_review")
       * @ORM\Entity
       */
      class InterviewReview
      {
          /**
           * @var integer
           *
           * @ORM\Column(name="id", type="integer")
           * @ORM\Id
           * @ORM\GeneratedValue(strategy="AUTO")
           */
          private $id;
      
          /**
           * @var Doctrine\Common\Collections\ArrayCollection
           *
           * @ORM\OneToMany(targetEntity="Absolvent\AbsolventBundle\Entity\InterviewReviewQuestion", cascade={"persist", "remove"}, mappedBy="interview_review")
           * @ORM\JoinColumn(name="interview_review", referencedColumnName="id")
           */
          private $questions;
      
          /**
           * Add question
           *
           * @param \Absolvent\AbsolventBundle\Entity\InterviewReviewQuestion $question
           * @return InterviewReview
           */
          public function addQuestion(\Absolvent\AbsolventBundle\Entity\InterviewReviewQuestion $question)
          {
              $this->questions[] = $question;
      
              return $this;
          }
      
          /**
           * Remove question
           *
           * @param \Absolvent\AbsolventBundle\Entity\InterviewReviewQuestion $question
           */
          public function removeQuestion(\Absolvent\AbsolventBundle\Entity\InterviewReviewQuestion $question)
          {
              $this->questions->removeElement($question);
          }
      
          /**
           * Get questions
           *
           * @return \Doctrine\Common\Collections\Collection
           */
          public function getQuestions()
          {
              return $this->questions;
          }
      }
      
      
      /**
       * InterviewReviewQuestion
       *
       * @ORM\Table(name="interview_review_question")
       * @ORM\Entity
       */
      class InterviewReviewQuestion
      {
          /**
           * @var integer
           *
           * @ORM\Column(name="id", type="integer")
           * @ORM\Id
           * @ORM\GeneratedValue(strategy="AUTO")
           */
          private $id;
      
          /**
           * @var Absolvent\AbsolventBundle\Entity\InterviewReview
           *
           * @ORM\ManyToOne(targetEntity="Absolvent\AbsolventBundle\Entity\InterviewReview", cascade={"persist", "remove"}, inversedBy="questions")
           * @ORM\JoinColumn(name="interview_review_id", referencedColumnName="id", nullable=false)
           */
          private $interview_review;
      
          /**
           * Get id
           *
           * @return integer
           */
          public function getId()
          {
              return $this->id;
          }
      
          /**
           * Set interview_review
           *
           * @param \Absolvent\AbsolventBundle\Entity\InterviewReview $interviewReview
           * @return InterviewReviewQuestion
           */
          public function setInterviewReview(\Absolvent\AbsolventBundle\Entity\InterviewReview $interviewReview = null)
          {
              $this->interview_review = $interviewReview;
      
              return $this;
          }
      
          /**
           * Get interview_review
           *
           * @return \Absolvent\AbsolventBundle\Entity\InterviewReview
           */
          public function getInterviewReview()
          {
              return $this->interview_review;
          }
      }
      

      This problem is causing because the is no $question->setInterviewReview() called anywhere.

      I know that i can call it inside addQuestion function, but is should work out of the box - isn't it?

        Activity

        Hide
        Marco Pivetta added a comment -

        Fixing code highlighting

        Show
        Marco Pivetta added a comment - Fixing code highlighting
        Hide
        Paweł Łaskarzewski added a comment -

        Fixed

        Show
        Paweł Łaskarzewski added a comment - Fixed
        Hide
        Marco Pivetta added a comment -

        Works here with your code. What's the exact ORM version you're using?

        Show
        Marco Pivetta added a comment - Works here with your code. What's the exact ORM version you're using?
        Hide
        Marco Pivetta added a comment -

        Calling

        $question->setInterviewReview($this);

        is up to you. Doctrine does not apply this kind of "magic".
        You are responsible for keeping your object graph consistent.

        Show
        Marco Pivetta added a comment - Calling $question->setInterviewReview($ this ); is up to you. Doctrine does not apply this kind of "magic". You are responsible for keeping your object graph consistent.
        Hide
        Paweł Łaskarzewski added a comment -

        In composer (using symofny) i have:

        "doctrine/orm": ">=2.2,<2.4-dev"

        and got the latest version.

        Lanuched composer update 2 hours ago

        Show
        Paweł Łaskarzewski added a comment - In composer (using symofny) i have: "doctrine/orm": ">=2.2,<2.4-dev" and got the latest version. Lanuched composer update 2 hours ago
        Hide
        Paweł Łaskarzewski added a comment -

        Ok but both objects are new and connected (using add function). I thought that cascade=

        {"persist"}

        will do this magic

        Show
        Paweł Łaskarzewski added a comment - Ok but both objects are new and connected (using add function). I thought that cascade= {"persist"} will do this magic
        Hide
        Marco Pivetta added a comment -

        No, associating them is up to you. The ORM is only responsible for saving/loading data, not for manipulating your associations like that.

        Show
        Marco Pivetta added a comment - No, associating them is up to you. The ORM is only responsible for saving/loading data, not for manipulating your associations like that.
        Hide
        Paweł Łaskarzewski added a comment -

        In the documentation there is some info about this:

        http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/working-with-associations.html#transitive-persistence-cascade-operations

        Even if you persist a new User that contains our new Comment this code would fail if you removed the call to EntityManager#persist($myFirstComment). Doctrine 2 does not cascade the persist operation to all nested entities that are new as well.
        [....]
        To have Doctrine handle both cases automatically we can change the User#commentsAuthored property to cascade both the “persist” and the “remove” operation.

        Show
        Paweł Łaskarzewski added a comment - In the documentation there is some info about this: http://docs.doctrine-project.org/projects/doctrine-orm/en/2.0.x/reference/working-with-associations.html#transitive-persistence-cascade-operations Even if you persist a new User that contains our new Comment this code would fail if you removed the call to EntityManager#persist($myFirstComment). Doctrine 2 does not cascade the persist operation to all nested entities that are new as well. [....] To have Doctrine handle both cases automatically we can change the User#commentsAuthored property to cascade both the “persist” and the “remove” operation.
        Hide
        Marco Pivetta added a comment -
        Show
        Marco Pivetta added a comment - Paweł Łaskarzewski see DDC-2227
        Hide
        Paweł Łaskarzewski added a comment -

        Ok thanks for your help

        Show
        Paweł Łaskarzewski added a comment - Ok thanks for your help

          People

          • Assignee:
            Marco Pivetta
            Reporter:
            Paweł Łaskarzewski
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: