9

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

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

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

4

2 回答 2

2

与其试图从这些情况中恢复,不如专注于防止违反完整性约束:

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

更新:

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

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

另一种解决方案是手动处理事务

$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 ,因为其中的数据(几乎总是)不再可用。

于 2013-03-26T09:20:01.090 回答
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

于 2014-04-30T15:21:51.547 回答