因此,在使用Doctrine2违反完整性约束之后,EntityManager喜欢以无法继续使用所述EntityManager的方式关闭。流行的想法似乎是你应该创建一个新的EntityManager,而不是被允许捕获这个简单的异常并以优雅的方式处理它(精彩的设计有人/讽刺)。
然而,当使用Bisna库/ ZF 1.12和封闭的实体管理器时会出现问题。 Bisna库不提供公共方法来在Container类中关闭后创建具有相同名称(即“默认”)的新EntityManager。
我的问题是处理这个问题的最佳方法是什么。在违反完整性约束之后,必须有一种方法可以优雅地恢复。
答案 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类在这里: