Doctrine2如何在回滚后处理更新实体?("EntityManager已关闭")

sie*_*iej 8 php doctrine symfony doctrine-orm

我正在尝试在事务中进行一些处理并保存有关潜在故障的信息,如下所示:

$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
}
Run Code Online (Sandbox Code Playgroud)

这看起来像一个非常常见的模式,但是Doctrine让它变得非常困难:

  1. flushcatch{}节会尽量坚持既$report$specification这显然是错误的对象,所以我可以clearentityManager,但后来......

  2. 如果我clearentityManager,$report通过它不再管理,所以我需要调用$em->merge($report),以使其再次进行管理.显然$user会保持不受管理,所以学说要么表现insert要么抱怨persist cascade.所以我可以是merge()整个图形(很糟糕)或者close是entityManager,但是...

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

我错过了什么吗?有没有其他方法来实现上述结果?我觉得Doctrine让事情变得简单.

Mar*_*Lie 5

简短答案

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

长答案

通常,您不能确定不会发生错误(刷新到数据库之前不会发生某些错误)。一旦发生,实体管理器将关闭营业。

这是我的工作(摘自config.yml):

doctrine:
    orm:
        default_entity_manager: 'default'
        entity_managers:
            default:
                mappings: { ... }
            logging:
                mappings: { ... }
Run Code Online (Sandbox Code Playgroud)

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

对于元操作(如记录批处理导入的进度或结果或类似操作),我明确获取了'logging'管理器并将其用于创建/更新日志记录/报告实体(并且仅用于那些实体)。