Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-117 Allow @Id on @ManyToOne fields
  3. DDC-922

Persisting an entity with an 1:n collection of related entites fails if the FK ist part of a composite PK

    Details

    • Type: Sub-task Sub-task
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-RC1
    • Fix Version/s: 2.1
    • Component/s: DQL, ORM
    • Security Level: All
    • Labels:
      None
    • Environment:
      Doctrine 2 RC 1 with sfDoctrine2Plugin using ORM, DBAL, Common and Symfony/Component for RC 1

      Description

      If you got two Entities A and B where A is a sample Entity with a 1:n relation to the Entity B
      and B has a composite PK with the FK (A id) and a custom field like this:

      EntityA:
        type: entity
        table: entity_a
        repositoryClass: EntityARepository
        id:
          id:
            type: integer
            generator:
              strategy: AUTO
        fields:
          handle:
            type: string
            length: 32
            unique: true
       oneToMany:
          entites_b:
            targetEntity: EntityB
            mappedBy: entity_a
            cascade: [persist]
      
      EntityB:
        type: entity
        table: entity_b
        repositoryClass: EntityBRepository
        id:
          description:
            type: string
            length: 255
            notnull: true
            generator:
              strategy: NONE
          entitiy_a_id:
            type: integer
            length: 11
            notnull: true
            generator:
              strategy: NONE
        fields:
          value:
            type: string
            length: 255
        manyToOne:
          entitiy_a:
            targetEntity: EntitiyA
            inversedBy: entities_b
      
      Class EntityA
      {
          private $id;
          
          private $handle;
          
          private $b_coll;
          
          public function addB(EntityB $ent) 
          {
              $this->b_coll->add($ent);
              $b->setA($this);
          }
      }
      
      Class EntityB
      {
          private $description;
          private $entity_a_id;
          
          private $value;
          
          private $entity_a;
          
          public function setA(EntityA $ent)
          {
              $this->entity_a = $ent;
          }
      }
      

      If you try to persist an object of A holding one or more references to objects of B, the objects get correctly persistet. This means, that every inserted record of B has a correctly filled field "entity_a_id". The objects of B also have a correct reference to A holding now the new A record with its autoinc id.
      But the object property "entity_a_id" stays empty. This leads to a collection of unusable EntityB objects (in memory), since on another persist of EntityA the values of entity_a_id are still not set correctly but the state is managed which leads to an "update B ... where entity_a_id=0"
      We've tried to set the entity_a_id with an event handler on postPersist. On a persist of EntityA the collection entities wanted to update their entity_a_ids from 0 to the correct one.

        Activity

        Florian Zumkeller-Quast created issue -
        Hide
        Benjamin Eberlei added a comment -

        Fixed formating

        Show
        Benjamin Eberlei added a comment - Fixed formating
        Benjamin Eberlei made changes -
        Field Original Value New Value
        Description
        If you got two Entities A and B where A is a sample Entity with a 1:n relation to the Entity B
        and B has a composite PK with the FK (A id) and a custom field like this:

        EntityA:
          type: entity
          table: entity_a
          repositoryClass: EntityARepository
          id:
            id:
              type: integer
              generator:
                strategy: AUTO
          fields:
            handle:
              type: string
              length: 32
              unique: true
         oneToMany:
            entites_b:
              targetEntity: EntityB
              mappedBy: entity_a
              cascade: [persist]
          

        EntityB:
          type: entity
          table: entity_b
          repositoryClass: EntityBRepository
          id:
            description:
              type: string
              length: 255
              notnull: true
              generator:
                strategy: NONE
            entitiy_a_id:
              type: integer
              length: 11
              notnull: true
              generator:
                strategy: NONE
          fields:
            value:
              type: string
              length: 255
          manyToOne:
            entitiy_a:
              targetEntity: EntitiyA
              inversedBy: entities_b


        Class EntityA
        {
            private $id;
            
            private $handle;
            
            private $b_coll;
            
            public function addB(EntityB $ent)
            {
                $this->b_coll->add($ent);
                $b->setA($this);
            }
        }

        Class EntityB
        {
            private $description;
            private $entity_a_id;
            
            private $value;
            
            private $entity_a;
            
            public function setA(EntityA $ent)
            {
                $this->entity_a = $ent;
            }
        }


        If you try to persist an object of A holding one or more references to objects of B, the objects get correctly persistet. This means, that every inserted record of B has a correctly filled field "entity_a_id". The objects of B also have a correct reference to A holding now the new A record with its autoinc id.
        But the object property "entity_a_id" stays empty. This leads to a collection of unusable EntityB objects (in memory), since on another persist of EntityA the values of entity_a_id are still not set correctly but the state is managed which leads to an "update B ... where entity_a_id=0"
        We've tried to set the entity_a_id with an event handler on postPersist. On a persist of EntityA the collection entities wanted to update their entity_a_ids from 0 to the correct one.

        If you got two Entities A and B where A is a sample Entity with a 1:n relation to the Entity B
        and B has a composite PK with the FK (A id) and a custom field like this:

        {code}
        EntityA:
          type: entity
          table: entity_a
          repositoryClass: EntityARepository
          id:
            id:
              type: integer
              generator:
                strategy: AUTO
          fields:
            handle:
              type: string
              length: 32
              unique: true
         oneToMany:
            entites_b:
              targetEntity: EntityB
              mappedBy: entity_a
              cascade: [persist]
        {code}

        {code}
        EntityB:
          type: entity
          table: entity_b
          repositoryClass: EntityBRepository
          id:
            description:
              type: string
              length: 255
              notnull: true
              generator:
                strategy: NONE
            entitiy_a_id:
              type: integer
              length: 11
              notnull: true
              generator:
                strategy: NONE
          fields:
            value:
              type: string
              length: 255
          manyToOne:
            entitiy_a:
              targetEntity: EntitiyA
              inversedBy: entities_b
        {code}

        {code}
        Class EntityA
        {
            private $id;
            
            private $handle;
            
            private $b_coll;
            
            public function addB(EntityB $ent)
            {
                $this->b_coll->add($ent);
                $b->setA($this);
            }
        }
        {code}

        {code}
        Class EntityB
        {
            private $description;
            private $entity_a_id;
            
            private $value;
            
            private $entity_a;
            
            public function setA(EntityA $ent)
            {
                $this->entity_a = $ent;
            }
        }
        {code}


        If you try to persist an object of A holding one or more references to objects of B, the objects get correctly persistet. This means, that every inserted record of B has a correctly filled field "entity_a_id". The objects of B also have a correct reference to A holding now the new A record with its autoinc id.
        But the object property "entity_a_id" stays empty. This leads to a collection of unusable EntityB objects (in memory), since on another persist of EntityA the values of entity_a_id are still not set correctly but the state is managed which leads to an "update B ... where entity_a_id=0"
        We've tried to set the entity_a_id with an event handler on postPersist. On a persist of EntityA the collection entities wanted to update their entity_a_ids from 0 to the correct one.

        Hide
        Benjamin Eberlei added a comment -

        When dealing with foreign keys as composite keys you are currently forced to make use of the "Assigned Id Generator".

        This means you have to make sure the IDs are set to their values before calling ->persist().

        Show
        Benjamin Eberlei added a comment - When dealing with foreign keys as composite keys you are currently forced to make use of the "Assigned Id Generator". This means you have to make sure the IDs are set to their values before calling ->persist().
        Hide
        Benjamin Eberlei added a comment -

        This issue will be fixed when DDC-117 is merged into master. That will happen for the 2.1 release.

        Show
        Benjamin Eberlei added a comment - This issue will be fixed when DDC-117 is merged into master. That will happen for the 2.1 release.
        Benjamin Eberlei made changes -
        Parent DDC-117 [ 10344 ]
        Issue Type Bug [ 1 ] Sub-task [ 5 ]
        Hide
        Benjamin Eberlei added a comment -

        Implemented

        Show
        Benjamin Eberlei added a comment - Implemented
        Benjamin Eberlei made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Assignee Roman S. Borschel [ romanb ] Benjamin Eberlei [ beberlei ]
        Fix Version/s 2.1 [ 10022 ]
        Resolution Fixed [ 1 ]
        Benjamin Eberlei made changes -
        Workflow jira [ 12212 ] jira-feedback [ 14682 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback [ 14682 ] jira-feedback2 [ 16546 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback2 [ 16546 ] jira-feedback3 [ 18799 ]

        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-922, expand=changesets[0:20].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)

          People

          • Assignee:
            Benjamin Eberlei
            Reporter:
            Florian Zumkeller-Quast
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: