5 votes

Doctrine2 échoue silencieusement à insérer des données

J'utilise Doctrine et il ne parvient pas à INSERT données la première fois que je fais un persist/flush mais fonctionne la deuxième fois, et échoue la troisième fois :

// there is no code executed between any of the attempts

$entity = new My\Entity();
$entity->setTag('A');  // just a random field
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, no entry is added

$entity = new My\Entity();
$entity->setTag('B');
$em->persist($entity);
$em->flush();
// INSERT performed
// if I exit here and check the database, 1 entry has been added
// and I can see it's "B"

$entity = new My\Entity();
$entity->setTag('C');
$em->persist($entity);
$em->flush();
// INSERT not performed
// if I exit here and check the database, there is still only 1 entry added
// and I can see it's "B"

Voici ce que je remarque lors des tentatives ratées :
- Il n'y a rien dans le PHP logs ( error_reporting est réglé sur tout, les autres problèmes de Doctrine et de PHP, y compris les avertissements, apparaissent dans les journaux).
- Le Doctrine SQLLogger n'affiche rien (à la deuxième tentative, il affiche l'adresse de l'entreprise). INSERT ).

Quelques étapes de dépannage :
- J'ai voulu pousser plus loin le dépannage en remplaçant la tentative ratée par une DQL INSERT demande mais "Les instructions INSERT ne sont pas autorisées dans DQL" :(
- Faire une flush avant d'instancier $entity dans l'échec de la tentative n'aide pas - Je peux insérer manuellement autant d'entrées que je veux dans la base de données et cela fonctionne, même à la première tentative.
- J'ai le même problème avec 2.4.0-DEV .
- J'ai le même problème avec 2.2.2 .

Je pourrais ajouter que le code est exécuté à l'intérieur d'un PHPunit et que dans un test précédent, je n'ai pas rencontré le problème (c'est-à-dire que Doctrine effectue correctement un test d'identification de l'utilisateur). INSERT sur le premier persist/flush ).

Une idée de l'origine du problème ?

Infos sur la version :
- PHP 5.4
- Doctrine 2.3.0 ( pdo_mysql conducteur)
- MySQL 5.5.24
- Ubuntu 12.04
- PHPUnit 3.7.7

Mise à jour 1 :

D'accord, voici une partie de la réponse. Le problème semble provenir d'une routine que j'utilise dans mon fichier PHPUnit setUp() pour tronquer les tables de ma base de données entre chaque test :

  • si je tronque mes tableaux entre chaque test, j'ai des problèmes (c'est-à-dire que certains INSERT échouent).
  • si je ne tronque pas, tout fonctionne bien.

La façon dont le INSERT semblent être plus aléatoires qu'on ne le pensait au départ, car j'ai créé 2 tests de 3 insertions chacun (et je n'ai exécuté que ceux-là). En tronquant les tables entre chaque test, voici ce qui arrive aux 3 insertions dans chaque test :
-test 1 : SUCCESSE / SUCCESSE / SUCCESSE
-test 2 : SUCCÈS / SUCCÈS / ÉCHEC (je n'ai plus d'ÉCHEC / SUCCÈS / ÉCHEC comme avant).

Voici le morceau de code que j'utilise pour tronquer les tableaux :

$cmd = $em->getClassMetadata($className);
$connection = $em->getConnection();
$dbPlatform = $connection->getDatabasePlatform();
$connection->beginTransaction();
try {
    $connection->query('SET FOREIGN_KEY_CHECKS=0');
    $q = $dbPlatform->getTruncateTableSql($cmd->getTableName());
    $connection->executeUpdate($q);
    $connection->query('SET FOREIGN_KEY_CHECKS=1');
    $connection->commit();
}
catch (\Exception $e) {
    $connection->rollback();
}

J'ai obtenu le code de ce poste SO et pour autant que je puisse voir, ça semble bon. J'ai le même problème si j'utilise cet autre code :

$connection = $entityManager->getConnection();
$platform   = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('my_table', true /* whether to cascade */));

J'ai modifié mon schéma pour le tester avec et sans les clés étrangères et j'ai le même problème dans les deux cas.

0voto

user359650 Points 2517

En fin de compte, il apparaît que le problème s'est produit lorsque :
-Truncation des tableaux entre chaque test dans les setUp fonction.
AND
-instanciant l'instance de la Doctrine une seule fois en setUpBeforeClass (que j'accédais alors avec self::$em ).

Si je ne tronque pas les tableaux entre chaque test OR si j'instancie mon instance de Doctrine en setUp tout fonctionne bien.

J'aimais bien setUpBeforeClass ...plus maintenant...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X