Symfony2:交易失败,“没有活动交易”。
Posted
技术标签:
【中文标题】Symfony2:交易失败,“没有活动交易”。【英文标题】:Symfony2: transactions fail with "There is no active transaction." 【发布时间】:2015-08-27 12:01:49 【问题描述】:我花了几个小时试图解决这个问题。谷歌和 *** 也没有多大帮助。因此,这里欢迎任何建议。
我正在尝试在更新两个相关表时对事务应用回滚逻辑:
一般的代码是:
// ...
$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() 没有任何工作,我得到 There is no active transaction. 异常。
一些消息来源建议只使用 commit() 而不使用 persist() ,但它没有任何区别。我可能在这里做了一些非常愚蠢的事情,但我就是看不到它是什么。
【问题讨论】:
我相信你需要在提交之前刷新,因为提交是在数据库级别,除了标记实体在下一次刷新时持久化之外,persist 并没有真正做任何事情,而刷新实际上执行查询,并且您必须先执行某种查询,然后才能提交。 @prodigitalson 你说的完全正确:我从 foreach 循环中删除了$em->getConnection()->commit()
,然后就在 $em->flush()
之前使用了它。现在就像一个魅力。谢谢!
嗯,要么你的解决方案出错,要么我错了。我的建议是刷新,然后提交。就我认为的问题而言,您解决的问题与您的初始代码略有不同。如果您发布的内容有效,那么它一定是您拥有的多个提交语句,因为那是本质上的变化。
另外你不应该用答案来修改你的问题......你可以回答你自己的问题,尽管在你可以将它标记为接受的答案之前有一个等待期。
@prodigitalson 我将解决方案移至自己的答案,谢谢。但实际上,一旦我删除了在persist() 之后的commits() 并且在flush() 之前只使用了一个commit() 就可以了。
【参考方案1】:
之后
$this->em->getConnection()->beginTransaction();
你必须写:
$this->em->getConnection()->setAutoCommit(false);
它对我有用:)
【讨论】:
【参考方案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】:从DoctrineBundle 1.5.2 版本开始,您可以在项目配置中配置连接以使用auto_commit
。
# app/config/config.yml (sf2-3) or config/doctrine.yaml (sf4)
doctrine:
dbal:
auto_commit: false
【讨论】:
不幸的是,这阻止了我的数据装置被刷新到数据库。【参考方案4】:正如@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;
【讨论】:
以上是关于Symfony2:交易失败,“没有活动交易”。的主要内容,如果未能解决你的问题,请参考以下文章
Symfony2 - 表单集合 delete_empty 失败
Symfony2 - 学说:模式:更新失败,实体在包之外(解耦)
Symfony2 - 奏鸣曲 Datagrid 过滤器操作符转换为教义_orm_class 字段失败