【问题标题】:Dealing with a closed EntityManager with Bisna/Doctrine2使用 Bisna/Doctrine2 处理封闭的 EntityManager
【发布时间】:2012-09-05 05:02:00
【问题描述】:

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

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

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

【问题讨论】:

标签: php zend-framework orm doctrine-orm


【解决方案1】:

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

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

更新:

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

【讨论】:

  • 有些场景你不可能事先知道。简单的例子是多个客户端连接到数据库,这显然很常见。他们可以在您检查到位后但在您的客户保存数据之前插入重复数据。你不能阻止这种情况,只能通过使用独占类型的数据库锁(我们真的不想要那些)。所以从这种类型的错误中恢复是相当必要的。
  • 我同意你应该在这种特殊情况下恢复,但很可能在同一个请求中不需要新的 EntityManager(因为用户/客户端需要重新评估他/她/它的输入)。 PS:Doctrine提供了锁,见docs.doctrine-project.org/projects/doctrine-orm/en/latest/…docs.doctrine-project.org/en/2.0.x/reference/…
【解决方案2】:

手动处理交易似乎对我没有用。即使我只使用 clear 方法,Doctrine 仍然关闭了实体管理器。我 fork 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-03
    • 2015-12-18
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 2018-04-19
    • 2013-08-20
    相关资源
    最近更新 更多