我正在使用Doctrine
,并且第一次进行persist/flush
时,它无法INSERT
数据,但第二次工作,并且失败了第三次:
// there is no code executed between any of the attempts
$entity = new MyEntity();
$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 MyEntity();
$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 MyEntity();
$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 logs
中没有什么(error_reporting
设置为所有,其他学说和PHP问题,包括警告,确实显示在日志中)。
-Doctrine SQLLogger
不显示任何内容(在第二次尝试中,它确实显示了INSERT
)。
一些故障排除步骤:
- 我想通过用DQL
INSERT
查询替换失败的尝试来进一步解决问题,但"在DQL中不允许插入语句" :(
- 在失败尝试中实例化$entity
之前,请执行额外的flush
无济于事 - 我可以手动插入任意数量的条目,即使在第一次尝试时也可以工作。
- 我对2.4.0-DEV
也有同样的问题。
- 我对2.2.2
也有同样的问题。
我可能会补充说,代码是在PHPunit
测试中执行的,并且在先前的测试中,我没有遇到问题(即学说确实在第一个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
S失败)。 - 如果我不截断,一切都可以罚款。
INSERT
s失败似乎是随机的模式,而不是最初想象的,因为我创建了2个测试,每个测试的3个测试(只能运行这些插入)。当每个测试之间截断表时,这是每个测试中的3个插入物所发生的事情:
-Test 1:成功/成功/成功
-test 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();
}
我从这篇文章中获得了代码,据我所知,它看起来不错。如果使用其他代码:
,我也有同样的问题$connection = $entityManager->getConnection();
$platform = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('my_table', true /* whether to cascade */));
我修改了我的模式以测试和没有外键,在两种情况下我都有相同的问题。
最终似乎发生了问题时发生的问题。 - 在setUp
函数中的每个测试之间截断表。
AND
- 在 setUpBeforeClass
中仅一次介绍一次学说实例(然后我使用 self::$em
访问)。
如果我在setUp
中实例化我的学说实例,则不截断每个测试OR
之间的表,则一切正常。
我曾经喜欢setUpBeforeClass
,不再是更多...