我正在使用 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:
好吧,这是答案的一部分。问题似乎是我在PHPUnit
的setUp()
中使用的例程,以在每个测试之间截断我的数据库表:- 如果我在每个测试之间截断我的表,我会遇到问题(即某些
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 */));
我修改了我的模式,测试了有和没有外键的情况,但两种情况下都存在同样的问题。