Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-1666

orphanRemoval does not work with oneToOne: Duplicate entry Error

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.2
    • Fix Version/s: 2.3.3
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      orphanRemoval does not work with oneToOne.
      Im getting "duplicate entry" errors after replacing the oneToOne object.
      Doctrine seems to insert the new data before removing the old one.
      if i remove the unique constraint by hand in the database it works.

      Mysql Error
      /*
      Error:
      SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UNIQ_9D8DDB05579B502F'
      */
      
      Models and YAML Mapping
      /*
      Contact:
        type: entity
        table: contact
        fields:
          _id:
            id: true
            type: integer
            unsigned: true
            nullable: false
            generator:
              strategy: AUTO
            column: id
        oneToOne:
          _standingData:
            targetEntity: StandingData
            mappedBy: _contact
            cascade: ["persist", "merge", "remove"] 
            orphanRemoval: true
      */
      
      class Contact
      {
          private $_id;
          private $_standingData;
      
          public function newStandingData(StandingData $sd)
          {
              $this->_standingData = $sd;
              $sd->setContact($this);
          }
      }
      
      /*
      StandingData:
        type: entity
        table: standing_data
        fields:
          _id:
            id: true
            type: integer
            unsigned: true
            nullable: false
            generator:
              strategy: AUTO
            column: id
        oneToOne:
          _contact:
            targetEntity: Contact
            inversedBy: _standingData
            joinColumns:
              contact_id:
                referencedColumnName: id
                onDelete: cascade
      */
      
      class StandingData
      {
          private $_id;
          private $_contact;
      
          public function setContact(Contact $c)
          {
              $this->_contact = $c;
          }
      }
      
      Script
      // Create new Contact
      $contact = new Contact();
      $contact->newStandingData(new \StandingData());
      $em->persist($contact);
      $em->flush();
      
      // Try to change StandingData
      $contact->newStandingData(new \StandingData());
      $em->flush();
      
      
      

        Issue Links

          Activity

          Mario Knippfeld created issue -
          Mario Knippfeld made changes -
          Field Original Value New Value
          Description orphanRemoval does not work with oneToOne.
          Im getting "duplicate entry" errors after replacing the oneToOne object:
          {code:title=Mysql Error}
          /*
          Error:
          SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UNIQ_9D8DDB05579B502F'
          */
          {code}

          {code:title=Models and YAML Mapping}

          /*
          Contact:
            type: entity
            table: contact
            fields:
              _id:
                id: true
                type: integer
                unsigned: true
                nullable: false
                generator:
                  strategy: AUTO
                column: id
            oneToOne:
              _standingData:
                targetEntity: StandingData
                mappedBy: _contact
                cascade: ["persist", "merge", "remove"]
                orphanRemoval: true
          */

          class Contact
          {
              private $_id;
              private $_standingData;

              public function newStandingData(StandingData $sd)
              {
                  $this->_standingData = $sd;
                  $sd->setContact($this);
              }
          }

          /*
          StandingData:
            type: entity
            table: standing_data
            fields:
              _id:
                id: true
                type: integer
                unsigned: true
                nullable: false
                generator:
                  strategy: AUTO
                column: id
            oneToOne:
              _contact:
                targetEntity: Contact
                inversedBy: _standingData
                joinColumns:
                  contact_id:
                    referencedColumnName: id
                    onDelete: cascade
          */

          class StandingData
          {
              private $_id;
              private $_contact;

              public function setContact(Contact $c)
              {
                  $this->_contact = $c;
              }
          }
          {code}


          {code:title=Script}
          // Create new Contact
          $contact = new Contact();
          $contact->newStandingData(new \StandingData());
          $em->persist($contact);
          $em->flush();

          // Try to change StandingData
          $contact->newStandingData(new \StandingData());
          $em->flush();


          {code}
          orphanRemoval does not work with oneToOne.
          Im getting "duplicate entry" errors after replacing the oneToOne object.
          Doctrine seems to insert the new data before removing the old one.
          if i remove the unique constraint by hand in the database it works.

          {code:title=Mysql Error}
          /*
          Error:
          SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '1' for key 'UNIQ_9D8DDB05579B502F'
          */
          {code}

          {code:title=Models and YAML Mapping}

          /*
          Contact:
            type: entity
            table: contact
            fields:
              _id:
                id: true
                type: integer
                unsigned: true
                nullable: false
                generator:
                  strategy: AUTO
                column: id
            oneToOne:
              _standingData:
                targetEntity: StandingData
                mappedBy: _contact
                cascade: ["persist", "merge", "remove"]
                orphanRemoval: true
          */

          class Contact
          {
              private $_id;
              private $_standingData;

              public function newStandingData(StandingData $sd)
              {
                  $this->_standingData = $sd;
                  $sd->setContact($this);
              }
          }

          /*
          StandingData:
            type: entity
            table: standing_data
            fields:
              _id:
                id: true
                type: integer
                unsigned: true
                nullable: false
                generator:
                  strategy: AUTO
                column: id
            oneToOne:
              _contact:
                targetEntity: Contact
                inversedBy: _standingData
                joinColumns:
                  contact_id:
                    referencedColumnName: id
                    onDelete: cascade
          */

          class StandingData
          {
              private $_id;
              private $_contact;

              public function setContact(Contact $c)
              {
                  $this->_contact = $c;
              }
          }
          {code}


          {code:title=Script}
          // Create new Contact
          $contact = new Contact();
          $contact->newStandingData(new \StandingData());
          $em->persist($contact);
          $em->flush();

          // Try to change StandingData
          $contact->newStandingData(new \StandingData());
          $em->flush();


          {code}
          Hide
          Benjamin Eberlei added a comment -

          This is a necessary restriction for the internals of Doctrine to always work correctly.

          Show
          Benjamin Eberlei added a comment - This is a necessary restriction for the internals of Doctrine to always work correctly.
          Benjamin Eberlei made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolution Can't Fix [ 7 ]
          Hide
          Albert Casademont added a comment -

          +1 on this one. So what's the point of orphanRemoval in OneToOne if it can never be done? Maybe onetoones should not create a unique index but a normal one.

          If it is really a won't fix, then the docs should reflect that.

          Show
          Albert Casademont added a comment - +1 on this one. So what's the point of orphanRemoval in OneToOne if it can never be done? Maybe onetoones should not create a unique index but a normal one. If it is really a won't fix, then the docs should reflect that.
          Hide
          Albert Casademont added a comment -

          BTW, as a workaround, i suggest converting this OneToOne case (where the orphanRemoval is in the inverse side) into a ManyToOne so a normal index will be created, not a unique one. Then the new row is inserted fine and the old one is deleted afterwards.

          Show
          Albert Casademont added a comment - BTW, as a workaround, i suggest converting this OneToOne case (where the orphanRemoval is in the inverse side) into a ManyToOne so a normal index will be created, not a unique one. Then the new row is inserted fine and the old one is deleted afterwards.
          Hide
          Mario Knippfeld added a comment - - edited

          +1
          like Albert said, if its really a wont fix, the docs should state that.
          the example in: http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html?highlight=orphan#orphan-removal with a (bidirectional) oneToOne orphanRemoval association isnt working with mysql and having doctrine created the tables.
          maybe the bidirectional association is the problem?

          Show
          Mario Knippfeld added a comment - - edited +1 like Albert said, if its really a wont fix, the docs should state that. the example in: http://readthedocs.org/docs/doctrine-orm/en/latest/reference/working-with-associations.html?highlight=orphan#orphan-removal with a (bidirectional) oneToOne orphanRemoval association isnt working with mysql and having doctrine created the tables. maybe the bidirectional association is the problem?
          Mario Knippfeld made changes -
          Resolution Can't Fix [ 7 ]
          Status Resolved [ 5 ] Reopened [ 4 ]
          Benjamin Eberlei made changes -
          Workflow jira [ 13471 ] jira-feedback [ 14105 ]
          Benjamin Eberlei made changes -
          Workflow jira-feedback [ 14105 ] jira-feedback2 [ 15969 ]
          Benjamin Eberlei made changes -
          Workflow jira-feedback2 [ 15969 ] jira-feedback3 [ 18223 ]
          Hide
          Matthieu Napoli added a comment -

          +1 same for me

          If the example of the docs isn't supposed to work (i.e. orphanRemoval with oneToOne isn't supported), then the docs should be updated.

          I can do a PR, but I need you to confirm it's really the case Benjamin Eberlei.

          Show
          Matthieu Napoli added a comment - +1 same for me If the example of the docs isn't supposed to work (i.e. orphanRemoval with oneToOne isn't supported), then the docs should be updated. I can do a PR, but I need you to confirm it's really the case Benjamin Eberlei .
          Hide
          Benjamin Eberlei added a comment -

          Its indeed a good fix to disable the unique constraint if orphan removal isset.

          Show
          Benjamin Eberlei added a comment - Its indeed a good fix to disable the unique constraint if orphan removal isset.
          Hide
          Benjamin Eberlei added a comment -

          Fixed and merged into 2.3

          With the change Doctrine will not create unique indexes anymore on Orphan Removal OneToOne associations. You need to change the database schema for this change to take effect essentially.

          Show
          Benjamin Eberlei added a comment - Fixed and merged into 2.3 With the change Doctrine will not create unique indexes anymore on Orphan Removal OneToOne associations. You need to change the database schema for this change to take effect essentially.
          Benjamin Eberlei made changes -
          Status Reopened [ 4 ] Resolved [ 5 ]
          Fix Version/s 2.3.3 [ 10329 ]
          Resolution Fixed [ 1 ]
          Ed Epstein made changes -
          Link This issue is referenced by DDC-3592 [ DDC-3592 ]

          This list may be incomplete, as errors occurred whilst retrieving source from linked applications:

          • Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={query=DDC-1666, expand=changesets[0:20].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

            People

            • Assignee:
              Benjamin Eberlei
              Reporter:
              Mario Knippfeld
            • Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: