beginTransaction(); try { $report = $reportRepository->-6ren">
gpt4 book ai didi

php - Doctrine2如何处理回滚后更新实体? ("The EntityManager is closed")

转载 作者:可可西里 更新时间:2023-11-01 12:36:21 30 4
gpt4 key购买 nike

我正在尝试在事务中进行一些处理并保存有关潜在失败的信息,就像这样:

$conn->beginTransaction();
try
{
$report = $reportRepository->find($id);
$user = $report->getUser();

$specification = new Specification();
$entityManager->persist($specification);

throw new ProcessingWentWrongException();

$entityManager->flush();
$conn->commit();
}
catch(ProcessingWentWrongException $e)
{
$conn->rollback();

// Store error info:
$report->setState('error');
$entityManager->persist($report);
$entityManager->flush(); // all hell breaks loose in here
}

这看起来是一个很常见的模式,但是 Doctrine 让它很难做到:

    catch{} 部分中的
  1. flush 将尝试保留 $report$specification 对象,这显然是错误的,所以我可以清除 entityManager,但是...

  2. 如果我清除 entityManager$report 不再由它管理,所以我需要调用 $em->merge($report) 让它再次被管理。显然 $user 将保持不受管理状态,因此 doctrine 将执行 insert 或提示 persist cascade。因此,我可以merge() 整个图(这很糟糕)或关闭 entityManager,但随后...

  3. 如果我关闭 entityManager 我只能通过$repo->find 重新检索report 实例($id); - 但我不想那样做,这很愚蠢。

我错过了什么吗?还有其他方法可以实现上述结果吗?我觉得 Doctrine 让容易的事情变得困难。

最佳答案

简答

使用两个实体管理器。一个用于潜在的不安全操作,一个用于记录/报告另一个。

长答案

通常,您无法确保错误不会发生(有些错误在您刷新到数据库之前不会发生)。一旦它们发生,entitymanager 就停止营业。

这是我所做的(摘自 config.yml):

doctrine:
orm:
default_entity_manager: 'default'
entity_managers:
default:
mappings: { ... }
logging:
mappings: { ... }

对于正常操作,我使用默认的实体管理器,不需要更改您的代码。

对于元操作(比如记录批量导入的进度或结果或类似的东西),我明确地获取 'logging' 管理器并使用它来创建/更新日志/报告实体(并且仅适用于那些)。

关于php - Doctrine2如何处理回滚后更新实体? ("The EntityManager is closed"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20247169/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com