【发布时间】:2012-10-18 12:03:02
【问题描述】:
我正在使用Doctrine,但在我第一次执行persist/flush 时它无法使用INSERT 数据,但第二次可以使用,第三次失败:
// 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 logs 中没有任何内容(error_reporting 设置为 all,其他 Doctrine 和 PHP 问题,包括警告,确实会显示在日志中)。
- Doctrine SQLLogger 没有显示任何内容(在第二次尝试时它确实显示了 INSERT)。
一些故障排除步骤:
- 我想通过用 DQL INSERT 查询替换失败尝试来进一步排除故障,但 "INSERT statements are not allowed in DQL" :(
- 在失败的尝试中实例化$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() 中使用的一个例程在每次测试之间截断我的数据库表:
- 如果我在每次测试之间截断我的表,我就会遇到问题(即一些
INSERTs 失败)。 - 如果我不截断,一切正常。
INSERTs 失败的方式似乎比最初想象的要随机,因为我创建了 2 个测试,每个测试 3 个插入(并且只运行了那些)。在每个测试之间截断表时,每个测试中的 3 个插入会发生以下情况:
-测试 1:成功/成功/成功
-test 2: SUCCESS / SUCCESS / FAILURE(我没有像以前那样有 FAILURE / SUCCESS / FAILURE)。
这是我用来截断表格的一段代码:
$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();
}
我从this SO post 获得了代码,据我所知,它看起来不错。如果我使用this other code,我也会遇到同样的问题:
$connection = $entityManager->getConnection();
$platform = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('my_table', true /* whether to cascade */));
我修改了我的架构以使用和不使用外键进行测试,在这两种情况下我都有同样的问题。
【问题讨论】:
-
你怎么知道它第一次不工作,第二次失败?
-
因为如果我在第一次尝试后退出并检查数据库,则没有插入任何条目。我会将它添加到代码 sn-p 中。
标签: php mysql insert doctrine-orm