使用Bisna / Doctrine2处理封闭的EntityManager

时间:2012-09-05 05:02:00

标签: php zend-framework orm doctrine-orm

因此,在使用Doctrine2违反完整性约束之后,EntityManager喜欢以无法继续使用所述EntityManager的方式关闭。流行的想法似乎是你应该创建一个新的EntityManager,而不是被允许捕获这个简单的异常并以优雅的方式处理它(精彩的设计有人/讽刺)。

然而,当使用Bisna库/ ZF 1.12和封闭的实体管理器时会出现问题。 Bisna库不提供公共方法来在Container类中关闭后创建具有相同名称(即“默认”)的新EntityManager。

我的问题是处理这个问题的最佳方法是什么。在违反完整性约束之后,必须有一种方法可以优雅地恢复。

2 个答案:

答案 0 :(得分:2)

不要试图从这些情况中恢复,而应该专注于防止违反完整性约束:

  • 如果您遇到外键约束,则不会以正确的方式将实体绑定在一起。
  • 如果您遇到唯一约束,则应在尝试保留数据之前检查数据库是否存在重复数据。
  • 如果您遇到其他类型的约束并且不知道如何阻止它,请询问:)

<强>更新

Doctrine2关闭EntityManager的原因是因为在大多数情况下它不再安全使用。它的UnitOfWork包含无法完成的操作(因此引发了异常)。

您是正确的,Bisna库不支持创建新的EntityManager。您可以扩展它以便自己实现此类功能。

另一个解决方案是handle transactions manually

$em->getConnection()->beginTransaction(); // suspend auto-commit
try {
    // do some work
    $user = new User;
    $user->setName('George');
    $em->persist($user);
    $em->flush();
    $em->getConnection()->commit();
} catch (Exception $e) {
    $em->getConnection()->rollback();
    $em->clear();  // in stead of $em->close();
    throw $e;
}

$em->close()替换为$em->clear(),您可以打开并清理EntityManager以便再次使用。

我强烈建议您 关闭清除 EntityManager,因为其中的数据(几乎总是)不再可用。

答案 1 :(得分:0)

手动处理交易似乎不适合我。即使我只使用了clear方法,Doctrine仍然关闭了实体管理器。我分叉了Bisna并对Container类做了一些修改,添加了一个“resetEntityManager”方法,看起来效果很好。

所以现在我的代码看起来像这样:

try {
    $user = new User;
    $user->setName('George');
    $em->persist($user);
    $em->flush();
} catch (Exception $e) {
    $dc = \Zend_Registry::get('doctrine'); //returns Bisna\Doctrine\Container
    $em = $dc->resetEntityManager();  //returns the new instance
    throw $e;
}

修订后的Container类在这里:

https://github.com/ajlozier/zendframework1-doctrine2/blob/ea46703e909149cba43edca56c91d5de2ab7a7f9/library/Bisna/Doctrine/Container.php