Symfony2:交易失败并显示“没有活动交易。”

时间:2015-06-11 16:48:11

标签: symfony pdo transactions doctrine rollback

我花了几个小时试图解决这个问题。谷歌和Stackoverflow也没有多大帮助。所以在这里欢迎任何建议。

我正在尝试在更新关系中的两个表时应用带有事务的回滚逻辑:

一般代码是:

// ...
$em = $this->getDoctrine()->getEntityManager();
$em->getConnection()->beginTransaction();

foreach($dataArr as $data) {
    $userObj = $em->getRepository('AcmeBundle:User')->find($userId);
    $userObj->setActive(1);
    $em->persist($userObj);
    $em->getConnection()->commit();
}

$storeObj = $em->getRepository('AcmeBundle:Store')->find($storeId);
$storeObj->setIsOpen(1);
$em->persist($storeObj);
$em->getConnection()->commit();

try {

    $em->flush();
    $em->clear();    

} catch(Exception $e) {

    $em->getConnection()->rollback();
    $em->close();
    throw $e;

}

我的PDO驱动程序已启用,更新没有事务按预期工作,但一旦我beginTransaction()并尝试commit()没有任何作用,我得到没有活动事务。异常。< / p>

有些消息来源建议只使用commit()而不使用persist(),但它没有任何区别。我可能在这里做了一些非常愚蠢的事情,但我看不出它是什么。

4 个答案:

答案 0 :(得分:4)

之后

$this->em->getConnection()->beginTransaction(); 

你必须写:

$this->em->getConnection()->setAutoCommit(false);

它对我有用:)

答案 1 :(得分:2)

正如@prodigitalson正确建议我需要在flush()之前执行commit()以便执行查询。所以现在的工作代码是:

$em = $this->getDoctrine()->getEntityManager();
$em->getConnection()->beginTransaction();

foreach($dataArr as $data) {
    $userObj = $em->getRepository('AcmeBundle:User')->find($userId);
    $userObj->setActive(1);
    $em->persist($userObj);
    // this is no longer needed
    // $em->getConnection()->commit();
}

$storeObj = $em->getRepository('AcmeBundle:Store')->find($storeId);
$storeObj->setIsOpen(1);
$em->persist($storeObj);
// this is no longer needed
// $em->getConnection()->commit();

try {

    // Do a commit before the FLUSH
    $em->getConnection()->commit();
    $em->flush();
    $em->clear();    

} catch(Exception $e) {

    $em->getConnection()->rollback();
    $em->close();
    throw $e;

}

答案 2 :(得分:2)

我偶然发现了这个错误 通过以下方式:

$em->getConnection()->beginTransaction();
try {
    $em->persist($entityA);
    $em->flush();

    $em->persist($entityB);
    $em->flush();

    $em->getConnection()->commit();
    //exception thrown here
    $mailer->send($from, $to, $subject, $text);
} catch (\Exception($ex)) {
    $em->getConnection()->rollback();
}

所以,你已经猜到在提交后不应该有任何代码,因为在这个仲裁代码(在我们的例子中是$ mailer服务)抛出异常事务将在执行catch块之前关闭。也许这会给某人节省一两分钟:))

答案 3 :(得分:0)

DoctrineBundle的1.5.2版本开始,您可以将连接配置为在项目的配置中使用auto_commit

# app/config/config.yml (sf2-3) or config/doctrine.yaml (sf4)
doctrine:
    dbal:
        auto_commit: false
相关问题