[DDC-231] YAML isn't persisting correcty Created: 30/Dec/09  Updated: 30/Dec/09  Resolved: 30/Dec/09

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: 2.0-ALPHA3
Fix Version/s: None
Security Level: All

Type: Bug Priority: Blocker
Reporter: Henrique Girardi dos Santos Assignee: Roman S. Borschel
Resolution: Invalid Votes: 0
Labels: None
Environment:

Ubuntu 9.04 -
PHP 5.3.1-0.dotdeb.0 with Suhosin-Patch (cli) (built: Nov 28 2009 13:18:25)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies
with Xdebug v2.0.5, Copyright (c) 2002-2008, by Derick Rethans
with Suhosin v0.9.29, Copyright (c) 2007, by SektionEins GmbH
-
PostgreSQL 8.3



 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 ?



 Comments   
Comment by Roman S. Borschel [ 30/Dec/09 ]

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.

Comment by Henrique Girardi dos Santos [ 30/Dec/09 ]

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?

Comment by Roman S. Borschel [ 30/Dec/09 ]

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...)

Comment by Henrique Girardi dos Santos [ 30/Dec/09 ]

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!

Generated at Sat Apr 19 07:22:25 UTC 2014 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.