Symfony 在多个实体管理器上处理条令事务
如果出现以下情况,则应回滚两个事务:Symfony 在多个实体管理器上处理条令事务,symfony,doctrine-orm,transactions,Symfony,Doctrine Orm,Transactions,如果出现以下情况,则应回滚两个事务: $em1失败,但$em2成功 $em1成功,但$em2失败 那么,我下面的例子是否正确处理涉及多个EMs的交易?我是在阅读了文档后想到的 $em1->getConnection()->beginTransaction(); $em2->getConnection()->beginTransaction(); try { $em1->persist($object1); $em1->flush();
$em1
失败,但$em2
成功$em1
成功,但$em2
失败$em1->getConnection()->beginTransaction();
$em2->getConnection()->beginTransaction();
try {
$em1->persist($object1);
$em1->flush();
$em1->getConnection()->commit();
$em2->persist($object2);
$em2->flush();
$em2->getConnection()->commit();
} catch (Exception $e) {
$em1->getConnection()->rollback();
$em2->getConnection()->rollback();
}
我之所以尝试实现这一点,是因为我得到了…导致了一个条令\ORM\orException异常(EntityManager已关闭)。
应用程序中的某个错误。我可能可以用下面的方法处理它,但我认为在上面的业务逻辑中使用事务更好
private function getNewEntityManager($em)
{
if (!$em->isOpen()) {
$em = $em->create($em->getConnection(), $em->getConfiguration());
}
return $em;
}
我想指出几件事,可能会让你头脑清醒: 我不知道创建第二个实体管理器的过程,请记住,两个完全不同的实体管理器不会共享相同的连接。您能指出两个不同实体管理器的使用案例吗 考虑到该行动:
$em1->getConnection()->commit();
将提交第一个事务,如果第二个事务出现错误,您将失去回滚该事务的权限
在抛出DBAL(数据库相关)异常后尝试操作任何提交/刷新操作时,这是典型的情况;在这种情况下,默认行为是关闭实体管理器。 通常的做法是在任何回滚后执行此操作:
$em1->getConnection()->rollback();
$em1->close();
希望有帮助,
尊敬。您的示例代码确实有效,这让我感到惊讶,因为Francesco Panina在
$em1->getConnection()->commit()方面是正确的(或者应该是正确的)
将提交第一个事务,如果第二个事务出现错误,您将失去[sic]回滚该事务的权限
然而,条令处理的方式意味着,当第二个事务出现错误时,实际上仍然可以回滚第一个事务
尽管如此,最佳做法是不依赖于此行为,而是将两个提交放在try块的最末端,如下所示:
$em1->getConnection()->beginTransaction();
$em2->getConnection()->beginTransaction();
try {
$em1->persist($object1);
$em1->flush();
$em2->persist($object2);
$em2->flush();
$em1->getConnection()->commit();
$em2->getConnection()->commit();
} catch (Exception $e) {
$em1->getConnection()->rollback();
$em2->getConnection()->rollback();
throw $e;
}
通过这一小改动,您的示例确实演示了处理跨多个实体经理的事务的正确方法。谢谢您的回答。第一个EM处理不同的数据库,第二个EM处理另一个数据库,因此业务逻辑被分离。我正试图调试其他人代码上的一个bug,因此,对于正在做的事情,我真的没有太多要说的。若要解决实际问题,我是否应该实现
getNewEntityManager($em)
方法,并在$em1->persist
和$em2->persist
之前调用它?你有什么建议?它会恢复EM并继续运行进程是否被关闭?考虑封闭的实体管理器是一个警报提示符,一些操作可能触发了一个低级别异常。我建议在持久化操作之前执行getNewEntityManager yes并调用目标刷新$em1->flush($entity)以避免链刷新其他实体。这方面运气好吗?我也有同样的问题。
$em1->getConnection()->beginTransaction();
$em2->getConnection()->beginTransaction();
try {
$em1->persist($object1);
$em1->flush();
$em2->persist($object2);
$em2->flush();
$em1->getConnection()->commit();
$em2->getConnection()->commit();
} catch (Exception $e) {
$em1->getConnection()->rollback();
$em2->getConnection()->rollback();
throw $e;
}