Doctrine2悄悄失败了数据插入

5

我正在使用 Doctrine,第一次执行 persist/flush 时无法插入数据,但第二次可以,第三次又失败了:

// 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"

以下是我在失败尝试中注意到的内容:
- PHP日志中没有任何内容(error_reporting设置为所有,其他Doctrine和PHP问题,包括警告,都会显示在日志中)。
- Doctrine SQLLogger没有显示任何内容(第二次尝试时它确实显示了INSERT)。
一些故障排除步骤:
- 我想通过用DQL INSERT查询替换失败的尝试来进一步进行故障排除,但是“DQL不允许使用INSERT语句”:(
- 在失败的尝试中,在实例化$entity之前执行额外的flush没有帮助。
- 我可以手动向数据库插入任意条目并且可以正常工作,即使在第一次尝试时也是如此。
- 我在2.4.0-DEV中遇到相同的问题。
- 我在2.2.2中遇到相同的问题。
我可能还要补充的是,代码在PHPUnit测试中执行,并且在以前的测试中,我没有遇到这个问题(即Doctrine在第一个persist/flush上正常执行INSERT)。 您有任何想法问题可能来自哪里? 版本信息:
- PHP 5.4
- Doctrine 2.3.0 (pdo_mysql驱动程序)
- MySQL 5.5.24
- Ubuntu 12.04
- PHPUnit 3.7.7

更新1:

好吧,这是答案的一部分。问题似乎是我在PHPUnitsetUp()中使用的例程,以在每个测试之间截断我的数据库表:
  • 如果我在每个测试之间截断我的表,我会遇到问题(即某些INSERT失败)。
  • 如果我不截断,一切都很好。
INSERT失败的方式似乎比最初想象的要随机,因为我创建了3个插入的2个测试(并且只运行了那些)。当在每个测试之间截断表时,以下是每个测试中3个插入的情况:
- 测试1:成功/成功/成功
- 测试2:成功/成功/失败(我没有像以前一样的失败/成功/失败)。
以下是我用来截断表格的代码片段:
$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();
}

我从这篇SO帖子中得到了代码,就我所看到的而言,它看起来很好。如果我使用这个其他的代码,我会遇到同样的问题:

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

我修改了我的模式,测试了有和没有外键的情况,但两种情况下都存在同样的问题。


第一次它为什么不起作用,第二次就失败了呢? - Jez
1
因为如果我在第一次尝试后退出并检查数据库,就不会插入任何条目。我将把它添加到代码片段中。 - Max
1个回答

0
最后,问题出现在以下情况:
- 在setUp函数中每个测试之间截断表格。
AND
- 仅在setUpBeforeClass中实例化Doctrine实例(然后使用self::$em访问)。

如果我不在每个测试之间截断表格OR,或者在setUp中实例化我的Doctrine实例,则一切正常。

我曾经喜欢setUpBeforeClass,但现在不再喜欢了...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接