【问题标题】:Doctrine2 silently fails to insert dataDoctrine2 静默插入数据失败
【发布时间】: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.0pdo_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


【解决方案1】:

最后,问题似乎发生在:
- 在setUp 函数中截断每个测试之间的表格。
AND
- 在 setUpBeforeClass 中仅实例化 Doctrine 实例一次(我当时正在使用 self::$em 访问)。

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

以前喜欢setUpBeforeClass,现在不喜欢了……

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多