Php 与具有Bisna/Doctrine2的封闭实体经理打交道
因此,在使用Doctrine2违反完整性约束后,EntityManager喜欢以一种无法继续使用所述EntityManager的方式关闭。流行的想法似乎是,您应该创建一个新的EntityManager,而不是被允许捕获这个简单的异常并以优雅的方式处理它(这里的设计很好/讽刺) 但是,在使用带有封闭实体管理器的Bisna库/ZF 1.12时,会出现一个问题。Bisna库不提供公共方法,在容器类中关闭EntityManager后,使用相同的名称(即“default”)创建新的EntityManagerPhp 与具有Bisna/Doctrine2的封闭实体经理打交道,php,zend-framework,orm,doctrine-orm,Php,Zend Framework,Orm,Doctrine Orm,因此,在使用Doctrine2违反完整性约束后,EntityManager喜欢以一种无法继续使用所述EntityManager的方式关闭。流行的想法似乎是,您应该创建一个新的EntityManager,而不是被允许捕获这个简单的异常并以优雅的方式处理它(这里的设计很好/讽刺) 但是,在使用带有封闭实体管理器的Bisna库/ZF 1.12时,会出现一个问题。Bisna库不提供公共方法,在容器类中关闭EntityManager后,使用相同的名称(即“default”)创建新的EntityManage
我的问题是什么是处理这个问题的最佳方式。必须有一种方法可以在违反完整性约束后优雅地恢复。不要试图从这些情况中恢复,您应该专注于防止违反完整性约束:
- 如果遇到外键约束,则表示没有以正确的方式将实体绑定在一起
- 如果遇到唯一约束,则应在尝试持久化之前检查数据库中是否存在可能的重复数据
- 如果您遇到另一种类型的约束,并且不知道如何防止它,请询问:)
$em->close()
替换为$em->clear()
,您可以保持EntityManager的打开和清洁,以便再次使用
我强烈建议您关闭或清除EntityManager,因为其中的数据(几乎总是)不再可用。手动处理事务似乎对我没有帮助。条令仍然关闭了实体管理器,即使我只使用了clear方法。我分叉了Bisna并对容器类进行了一些修改,添加了一个“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;
}
修订后的集装箱类别如下:
使用条令注册表可能会重置关闭的实体管理器。请看,有些情况下,您可能无法事先知道。简单的例子是多个客户端连接到数据库,这显然很常见。他们可以在您办理入住手续后但在您的客户保存数据之前插入重复数据。您不能仅仅通过使用排他类型的数据库锁来防止这种情况(实际上,我们并不需要这些锁)。因此,从这种类型的错误中恢复是非常必要的。我同意您应该在这种特殊情况下进行恢复,但很可能不需要在同一请求中使用新的EntityManager(因为用户/客户端需要重新评估其输入)。PS:条令提供锁定,请参见和
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;
}