IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Doctrine2 PHP Discussion :

Doctrine2 ne respecte pas l'ordre des opérations sur les collections?


Sujet :

Doctrine2 PHP

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2011
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 8
    Points : 9
    Points
    9
    Par défaut Doctrine2 ne respecte pas l'ordre des opérations sur les collections?
    Bonjour,

    Effet recherché:
    1. vider une collection doctrine (One-to-many)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $myEvent->getRegistrations()->clear()
    2. ajouter de nouveaux membres à cette collection
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $myEvent->addRegistration($myRegistration)
    3. enregistrer en base de donnée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $em->persist($myEvent); $em->flush();

    Constatation:
    Après de nombreux essais, lors du flush final, l'insertion de la nouvelle Registration se fait avant le delete des autres Registrations de la collection.
    Apparemment, doctrine2 ne respecte pas l'ordre dans lequel sont effectuées ces opérations si on ne met qu'un seul flush à la fin (en 3), et il faut mettre en plus un flush entre 1) et 2) pour que ça fonctionne.

    Question:
    Est-ce que ma constation est juste?
    Mais dans ce cas, est-ce qu'il ne serait pas logique que doctrine gère ce worflow de façon transparente, et réalise les opérations dans le bonne ordre lors du flush en 3) ?

    Détail de mon test:
    • Mes relations: Event <= One-to-Many => Registrations <=Many-to-One => User
    • Ma DB contient déjà des Registrations pour l'Event traité ici
    • j'ai une contrainte Unique sur la propriété User de mes entités Registration (colonne event_user)
    • Raison pour laquelle je souhaite avoir qu'un seul flush: pendant que je travaille sur l'entité en mémoire, je souhaite par la suite faire un detach pour récupérer l'ancienne entité dans la base et examiner les différences entre l'ancienne et la nouvelle.


    Avec le code suivant, j'obtiens une exception due à la violation sur la clef étrangère user, ce qui indique que les Registrations n'ont pas été supprimées en base de donnée avant l'insertion (la base de donnée contient déjà des Registrations, dont une pour l'utilisateur 1 que j'ajoute aprés):

    An exception occurred while executing 'INSERT INTO Registration (createdAt, updatedAt, numparticipant, numqueuedparticipant, organizer, user_id, event_id) VALUES (?, ?, ?, ?, ?, ?, ?)' with params ["2014-07-12 20:32:26", "2014-07-12 20:32:26", 10, 0, 1, 1, 114]:

    SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '114-1' for key 'event_user'
    Définition de la relation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    Cpt\EventBundle\Entity\Event:
        type: entity
        oneToMany:
            registrations:
                targetEntity: Registration
                mappedBy: event
                indexBy: user_id
                cascade: ["persist","detach","merge"]
                orphanRemoval: true
     
    Cpt\EventBundle\Entity\Registration:
      type: entity
          event:
            targetEntity: Event
            inversedBy: registrations
            joinColumn:
              name: event_id
              referencedColumnName: id
              onDelete: CASCADE
    Voilà mon code de test:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
       public function testAction()
        {
           try{
               // Récupérer l'Event 114 déjà en base de donnée
                $event = $this->getEventManager()->getEventById(114);
     
                // Supprimer toutes les registrations (j'ai essayé avec la boucle foreach mais sans le collection->clear() et inversement, et avec les deux
               foreach($event->getRegistrations() as $registration){
                    $event->removeRegistration($registration);
                    $this->getDoctrine()->getManager()->remove($registration);
               }
               $event->getRegistrations()->clear();
     
               // Persist l'Event - J'ai essayé avec et sans ce persist
               $this->getDoctrine()->getManager()->persist($event);
     
               // Créer une nouvelle Registration et l'ajouter à la collection
               $user = $this->getUserManager()->findUserBy(Array("id" => 1));
                $registration = $this->getRegistrationManager()->CreateRegistration($event, $user, 10, true );
                $event->addRegistration($registration);
     
                // Persist et Flush l'Event
                $this->getDoctrine()->getManager()->persist($event);
                $this->getDoctrine()->getManager()->flush();
            } catch (\Exception $e) {
                throw $e;
            }
        }
    le removeRegistration de l'entité event:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        public function removeRegistration(\Cpt\EventBundle\Entity\Registration $registrations)
        {
            $this->registrations->removeElement($registrations);
            $registrations->setEvent(null);
        }

  2. #2
    Membre émérite Avatar de darkstar123456
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2008
    Messages
    1 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 896
    Points : 2 835
    Points
    2 835
    Par défaut
    Bonjour,

    Je ne m'y connais pas vraiment en Doctrine mais de ce que j'en sais clear() ne fait que détacher l'identité, elle ne la supprime pas.
    Ne devriez vous pas utiliser remove() à la place de clear() ?

  3. #3
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Bonjour,

    Quelqu'un peut-il confirmer ce qui est décrit par le post de rocknroll.

    Je fais le même constant aujourd'hui : sur une relation OneToMany avec orphanRemoval=true, si au niveau de l'ArrayCollection un clear() est réalisé puis un add(), lors des instructions SQL l'insertion est exécutée en premier ce qui peut poser des problèmes d'unicité car ce que l'on imaginait supprimé par le clear() ne l'a pas encore été.

    Existe-t-il une bonne raison pour que Doctrine se comporte de la sorte ?

    Merci

  4. #4
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    397
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 397
    Points : 133
    Points
    133
    Par défaut
    Voici quelques explications :

    https://github.com/doctrine/doctrine2/issues/5109

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    The order is:
     
    1) all entity inserts (topological order)
    2) all entity updates (topological order)
    3) all collection deletions
    4) all collection updates
    5) all entity deletions (reverse toplogical order)
     
    Where the topological order is dictated by the foreign key constraints.

Discussions similaires

  1. complexité des opérations sur les vector
    Par Gwindor dans le forum SL & STL
    Réponses: 14
    Dernier message: 10/07/2008, 20h37
  2. Des opérations sur les mots
    Par nadia27 dans le forum Débuter
    Réponses: 5
    Dernier message: 05/01/2008, 14h18
  3. [Form] GoToRecord ne respecte pas l'ordre des dates
    Par Zawawi dans le forum VBA Access
    Réponses: 3
    Dernier message: 15/11/2007, 09h22
  4. [2.0] Comment réaliser des opérations sur les ensembles ?
    Par Cereal123 dans le forum Framework .NET
    Réponses: 2
    Dernier message: 23/10/2006, 14h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo