2016-10-06 1 views
1

Meine Frage könnte ein Duplikat von this one sein, aber ich kann keine befriedigende Antwort finden, also werde ich versuchen, dies genauer zu machen.Überprüfen Sie die Existenz in Doctrine für persistente und nicht persistente Entitäten

Ich baue einen Import-Service von einer anderen API. Und ich möchte kein Duplikat in meiner neuen Datenbank.

So, hier ein Beispiel meiner aktuellen Implementierung:

Der Controller:

public function mainAction() 
{ 
    $em = $this->getDoctrine()->getManager(); 

    $persons_data = [ 
     [ 
      'first_name' => 'John', 
      'last_name' => 'Doe' 
     ], 
     [ 
      'first_name' => 'John', 
      'last_name' => 'Doe' 
     ] 
    ]; 

    $array = []; 

    foreach($persons_data as $person_data) 
    { 
     $person = $this->get('my_service')->findOrCreatePerson($person_data); 
     $array[] = $person; 
    } 

    $em->flush(); 

    return new Response(); 
} 

Eine Servicefunktion:

public function findOrCreatePerson ($data) 
{ 
    $em = $this->em; 

    $person = $em->getRepository('AppBundle:Person')->findOneBy([ 
     'first_name' => $data['first_name'], 
     'last_name' => $data['last_name'] 
    ]); 

    if(is_null($person)) { 
     $person = new Person(); 
     $person->setFirstName($data['first_name']); 
     $person->setLastName($data['last_name']); 
     $em->persist($person); 
    } 

    return $person 
} 

Ich habe versucht, es so einfach wie möglich zu machen.

Wie Sie sehen können, möchte ich nur eine DB-Transaktion machen, um einige Leistungsverbesserungen zu erhalten.

Problem ist, wenn ich nicht am Ende der findOrCreatePerson() Methode flush, wird die Abfrage an die Person Repository das erste Objekt nicht finden und wird Duplikate in der Datenbank erstellen.

Meine Frage ist einfach: Wie soll ich so etwas umsetzen?

Antwort

3

Dies ist ein Job für Memoize!

+1

Große Sache zu wissen, danke! – Hammerbot

2

Cerad Antwort (Memo) ist eine gute, aber ich würde Sie ermutigen, etwas zu überdenken.

Wie Sie sehen können, möchte ich nur eine DB-Transaktion machen, um einige Leistungsverbesserungen zu erhalten.

Und es gibt ein paar Dinge mit diesem Satz falsch.

Die wichtigste ist, dass Sie flush() mit einer einzigen, atomaren Transaktion zusammenführen. Sie können Transaktionsgrenzen manuell verwalten, was oft sehr vorteilhaft ist.

Die zweite Sache ist, dass wenn Sie über Massenimporte sprechen, Sie schnell erfahren, dass das erste Leistungsproblem, das Sie getroffen haben, überhaupt nicht die Datenbank ist. Es ist der EntityManager selbst. Wenn die interne Identitätskarte des EMs anschwillt, werden die Änderungen am Computer sehr langsam.

Ich würde in Erwägung ziehen, Ihre Kernschleife wie folgt neu zu schreiben und zu sehen, ob es schnell genug ist. Denken Sie nur dann an eine Memoisierung, wenn dies erforderlich ist.

$em->beginTransaction(); 
foreach($persons_data as $person_data) 
{ 
    $person = $this->get('my_service')->findOrCreatePerson($person_data); 
    $em->flush(); 
    $em->clear(); // don't keep previously inserted entities in the EM. 
} 
$em->commit(); 
+0

Vielen Dank für Ihre Antwort. Eigentlich habe ich bereits Operationen aufgeteilt. Der wirkliche Fall war der folgende. Ich musste eine alte Benutzerdatenbank importieren. Ich entschied mich, mehrere Transaktionen von 200 Benutzern zu machen. Das Problem trat ein, als ich mehrere Adressen jedes Benutzers importierte. Also hatte jeder Benutzer nur eine oder zwei Adressen und ich wollte diese nicht jedes Mal löschen. – Hammerbot

+1

Hallo @timdev, nach einem Tag des Nachdenkens, ich glaube, ich verstehe endlich, was du meinst. Ich habe tatsächlich keine Transaktionen verwendet, wie Sie es mir gezeigt haben, und ich denke, dass ich es auch nutzen werde, kombiniert mit Memoization. Also ein großes Dankeschön auch an Sie für die Informationen, dieses Thema hat mich dazu gebracht, zwei wichtige Dinge zu lernen! – Hammerbot

+0

@El_Matella Ich bin froh, dass du es herausgefunden hast. Ich war mir nicht sicher, hatte aber gestern keine Zeit, um darauf einzugehen. Sobald Sie mit der manuellen Verwaltung von Transaktionen beginnen, werden Sie immer mehr Stellen finden, an denen dies vorteilhaft ist. – timdev

Verwandte Themen