我花了几个小时试图解决这个问题。谷歌和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(),但它没有任何区别。我可能在这里做了一些非常愚蠢的事情,但我看不出它是什么。
答案 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