Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Blocker Blocker
    • Resolution: Invalid
    • Affects Version/s: 2.0-ALPHA3
    • Fix Version/s: None
    • Component/s: None
    • Security Level: All
    • Labels:
      None
    • Environment:

      Description

      I'm have some problems when I try to persist..
      I've created these classes:

      class Customer
      {
          public $id;
          public $users;
      
          public function __construct()
          {
              $this->users = new \Doctrine\Common\Collections\ArrayCollection();
          }
      }
      
      class User
      {
          public $id;
          public $customer;
      }
      
      

      And then I make the mappers with YAML

      Ciutat\DomainModel\Customer:
        type: entity
        table: customer
        fields:
          id:
            type: integer
            id: true
            generator:
              strategy: auto
            sequenceGenerator:
              sequenceName: customer_id_seq
              allocationSize: 1
              initialValue: 1
        oneToMany:
          users:
            targetEntity: User
            mappedBy: customer
            cascade: cascadePersist
      
      Ciutat\DomainModel\User:
        type: entity
        table: user1
        fields:
          id:
            type: integer
            id: true
            generator:
              strategy: auto
            sequenceGenerator:
              sequenceName: user1_id_seq
              allocationSize: 1
              initialValue: 1
        manyToOne:
          customer:
            targetEntity: Customer
            joinColumn:
              name: customerId
              referencedColumnName: id
      

      And when I try to persist some data

      $costumer = new DomainModel\Customer();
      $user = new DomainModel\User();
      $user2 = new DomainModel\User();
      $user3 = new DomainModel\User();
      
      $costumer->users->add($user);
      $costumer->users->add($user2);
      $costumer->users->add($user3);
          
      $em->persist($costumer);
      $em->flush();
      

      the result in my database is not what I think it must be expected

      select * from customer;
       id 
      ----
        1
      
      elect * from user1;
       id | customerid 
      ----+------------
        1 |           
        2 |           
        3 |           
      
      

      I would like to know if have some mistake with my code or is there a problem with YAML? 'cause I think there should be some data on 'customerId', don't I ?

        Activity

        Henrique Girardi dos Santos created issue -
        Henrique Girardi dos Santos made changes -
        Field Original Value New Value
        Summary YAML isn't persisting YAML isn't persisting correcty
        Hide
        Roman S. Borschel added a comment -

        This is expected behavior. You must maintain the bidirectional association properly. Doctrine only looks at the "owning side" of a bidirectional association. In the case of a bidirectional one-to-many, like in your case, the owning side is always the many-side. Since you only add the elements to the collection, but dont set the customer property pointing back to the customer, the association does not exist for Doctrine.

        Change your code to:

        $costumer = new DomainModel\Customer();
        $user = new DomainModel\User();
        $user2 = new DomainModel\User();
        $user3 = new DomainModel\User();
        
        $costumer->users->add($user);
        $user->customer = $costumer;
        $costumer->users->add($user2);
        $user2->customer = $costumer;
        $costumer->users->add($user3);
        $user3->customer = $costumer;
        
        $em->persist($costumer);
        $em->flush();
        

        And it should work.

        Please read this section carefully: http://www.doctrine-project.org/documentation/manual/2_0/en/association-mapping#owning-side-and-inverse-side

        Its a simple, yet essential concept to understand.

        Hope that helps.

        Show
        Roman S. Borschel added a comment - This is expected behavior. You must maintain the bidirectional association properly. Doctrine only looks at the "owning side" of a bidirectional association. In the case of a bidirectional one-to-many, like in your case, the owning side is always the many-side. Since you only add the elements to the collection, but dont set the customer property pointing back to the customer, the association does not exist for Doctrine. Change your code to: $costumer = new DomainModel\Customer(); $user = new DomainModel\User(); $user2 = new DomainModel\User(); $user3 = new DomainModel\User(); $costumer->users->add($user); $user->customer = $costumer; $costumer->users->add($user2); $user2->customer = $costumer; $costumer->users->add($user3); $user3->customer = $costumer; $em->persist($costumer); $em->flush(); And it should work. Please read this section carefully: http://www.doctrine-project.org/documentation/manual/2_0/en/association-mapping#owning-side-and-inverse-side Its a simple, yet essential concept to understand. Hope that helps.
        Roman S. Borschel made changes -
        Status Open [ 1 ] Resolved [ 5 ]
        Resolution Invalid [ 6 ]
        Hide
        Henrique Girardi dos Santos added a comment -

        I did this way sometime ago but I thought I was a mistake mine..but I see i was correct..
        I created a prePersist method where I did it automatic and a postPersist to unset after that, cause I dont see any another reason to keep all my object customer inside the User class if inside Customer I have a User collection, so I know which Users belong to Customer..

        why I need to set

        oneToMany:
            users:
              targetEntity: User
              mappedBy: customer
              cascade: cascadePersist
        

        in Customer?? I thought if I set the target and the mappedBy it would be enough..can't it be automatic? Or it's impossible?

        Show
        Henrique Girardi dos Santos added a comment - I did this way sometime ago but I thought I was a mistake mine..but I see i was correct.. I created a prePersist method where I did it automatic and a postPersist to unset after that, cause I dont see any another reason to keep all my object customer inside the User class if inside Customer I have a User collection, so I know which Users belong to Customer.. why I need to set oneToMany: users: targetEntity: User mappedBy: customer cascade: cascadePersist in Customer?? I thought if I set the target and the mappedBy it would be enough..can't it be automatic? Or it's impossible?
        Hide
        Roman S. Borschel added a comment -

        You dont need prePersist or postPersist. You just need to maintain your bidirectional associations properly. This is nothing doctrine specific, basic OOP.

        And it is not automatic because this would break transparency. Its not the task of the ORM to fix your broken associations. Then your object model is suddenly broken without the persistence layer.

        If you want a unidirectional one-to-many, you must map it through a join table. Its all in the documentation.

        The behavior is very consistent and predictable (compared to what D1 does, for example...)

        Show
        Roman S. Borschel added a comment - You dont need prePersist or postPersist. You just need to maintain your bidirectional associations properly. This is nothing doctrine specific, basic OOP. And it is not automatic because this would break transparency. Its not the task of the ORM to fix your broken associations. Then your object model is suddenly broken without the persistence layer. If you want a unidirectional one-to-many, you must map it through a join table. Its all in the documentation. The behavior is very consistent and predictable (compared to what D1 does, for example...)
        Hide
        Henrique Girardi dos Santos added a comment -

        I know I dont need prePersist or postPersist, It was just my choice, I just created them to make it automaticaly..
        and I don't want a unidirectional..there's no reason to have another table to join them..
        but now I understood why it's not automatic..

        thanks man!

        Show
        Henrique Girardi dos Santos added a comment - I know I dont need prePersist or postPersist, It was just my choice, I just created them to make it automaticaly.. and I don't want a unidirectional..there's no reason to have another table to join them.. but now I understood why it's not automatic.. thanks man!
        Benjamin Eberlei made changes -
        Workflow jira [ 10668 ] jira-feedback [ 14215 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback [ 14215 ] jira-feedback2 [ 16079 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback2 [ 16079 ] jira-feedback3 [ 18332 ]

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

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Henrique Girardi dos Santos
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: