Die Überschreibung der Strategie zur Generierung von Standard-IDs hat keine Auswirkungen auf Zuordnungen

8

Symfony 2.7.2. Lehre ORM 2.4.7. MySQL 5.6.12. PHP 5.5.0.
Ich habe eine Entität mit einer benutzerdefinierten ID-Generatorstrategie. Es funktioniert einwandfrei.
Unter Umständen muss ich diese Strategie mit einer "handgemachten" ID überschreiben. Es funktioniert, wenn die Haupteinheit ohne Assoziationen gelöscht wird. Aber es funktioniert nicht mit Assoziationen. Dieser Beispielfehler wird ausgelöst:

  

Beim Ausführen von 'INSERT INTO articles_tags (article_id, tag_id) VALUES (?,?)' mit params ["a004r0", 4] ist eine Ausnahme eingetreten:

     

SQLSTATE [23000]: Integritätseinschränkungsverletzung: 1452 Hinzufügen oder Aktualisieren einer untergeordneten Zeile nicht möglich: Eine Fremdschlüsseleinschränkung schlägt fehl ( sf-test1 . articles_tags , CONSTRAINT FK_354053617294869C FREMDSCHLÜSSEL ( article_id ) REFERENCES article ( id ) ON DELETE CASCADE)

So reproduzieren Sie:

  1. Installieren und erstellen Sie eine Symfony2-Anwendung .
  2. Bearbeiten Sie app/config/parameters.yml mit Ihren DB-Parametern.
  3. Erstellen Sie mithilfe des Beispiel-Namespaces AppBundle die Entitäten Article und Tag im Verzeichnis src/AppBundle/Entity .

    %Vor% %Vor%
  4. Erzeuge Getter und Setter für die obigen Entitäten:

    %Vor%
  5. Erstellen Sie ArticleNumberGenerator class in src/AppBundle/Doctrine :

    %Vor%
  6. Datenbank erstellen: php app/console doctrine:database:create .

  7. Erstellen Sie Tabellen: php app/console doctrine:schema:create .
  8. Bearbeiten Sie das Beispiel AppBundle DefaultController in src\AppBundle\Controller . Ersetzen Sie den Inhalt durch:

    %Vor%
  9. Server ausführen: php app/console server:run .

  10. Navigieren Sie zu Ссылка . Aktualisieren Sie 2 Mal, um diese Nachricht zu sehen:

      

    Erstellte Artikel-ID a003r0.

  11. Navigieren Sie nun zu Ссылка . Das erwartete Ergebnis ist:

      

    Erstellte Artikel-ID test1.

    , stattdessen erhalten Sie den Fehler:

      

    Beim Ausführen von 'INSERT INTO articles_tags (article_id, tag_id) VALUES (?,?)' mit params ["a004r0", 4] ist eine Ausnahme eingetreten:

         

    SQLSTATE [23000]: Integritätseinschränkungsverletzung: 1452 Hinzufügen oder Aktualisieren einer untergeordneten Zeile nicht möglich: Eine Fremdschlüsseleinschränkung schlägt fehl ( sf-test1 . articles_tags , CONSTRAINT FK_354053617294869C FREMDSCHLÜSSEL ( article_id ) REFERENCES article ( id ) ON DELETE CASCADE)

    offensichtlich, weil Artikel mit id "a004r0" nicht existiert.

Wenn ich $article->getTags()->add($tag); in createHandmadeAction auskommentiere, funktioniert es - das Ergebnis ist:

  

Erstellt Artikel-ID-Test.

und die Datenbank wird entsprechend aktualisiert:

%Vor%

, aber nicht, wenn eine Beziehung hinzugefügt wird. Aus einem Grund verwendet Doctrine nicht das handgemachte id für Assoziationen, sondern verwendet die Standard-Id-Generator-Strategie.

Was ist hier falsch? Wie kann ich den Entity Manager davon überzeugen, meine handgefertigten Ids für Assoziationen zu verwenden?

    
bostaf 23.07.2015, 17:32
quelle

1 Antwort

4

Ihr Problem hängt mit dem Aufruf von $em->persist($article); zusammen, bevor Sie ClassMetadata ändern.

Wenn die neue Entität beibehalten wird, generiert UnitOfWork id mit ArticleNumberGenerator und speichert sie im Feld entityIdentifiers . Später ManyToManyPersister verwendet diesen Wert mit Hilfe von PersistentCollection beim Füllen der Relationstabellenzeile.

Beim Aufruf von flush UoW berechnet den Änderungssatz der Entität und speichert den tatsächlichen ID-Wert - deshalb erhalten Sie korrekte Daten, nachdem Sie keine Assoziation hinzugefügt haben. Aber es aktualisiert Daten von entityIdentifiers nicht.

Um das zu beheben, könnten Sie persist einfach hinter das Ändern des ClassMetadata-Objekts verschieben. Aber der Weg sieht immer noch aus wie Hack. IMO ist der optimale Weg, den benutzerdefinierten Generator zu schreiben, der zugewiesene ID verwenden wird, wenn die eine bereitgestellt wird, oder neue generieren.

PS . Die andere Sache, die berücksichtigt werden sollte - Ihre Art der Generierung ID ist nicht sicher, es wird doppelte IDs auf der Hochlast produzieren.

UPD Verpasst, dass UoW nicht idGeneratorType verwendet (es wird von metadata factory verwendet, um den richtigen Wert für idGenerator zu setzen), also sollten Sie die richtige idGenerator

setzen %Vor%

Das funktioniert wie erwartet.

    
origaminal 05.08.2015, 14:34
quelle