Doctrine:如何通过捕获异常防止事务成为“rollback only”?

3

由于postRemove事件处理程序中的异常,删除实体失败。即使捕获了异常,删除也会失败,因为事务无法再提交。 如何解决这个问题?

完整的故事:

我需要在基于Symfony 3.4Doctrine的Web服务中跟踪一些已删除的实体。

为此,我创建了一个EventSubscriber来处理postRemove事件,以检查是否需要记录已删除的实体。在这种情况下,实体的UUID存储在DB的DeleteLog表中。

这很好用,但在某些罕见情况下,持久化DeleteLogEntry失败,因为给定UUID的日志条目已经存在,需要是唯一的。

这个问题的根源是一些我无法自行更改的第三方代码。作为临时解决方案,我试图捕获UniqueConstraintViolationException。这并不能解决问题,因为现在我得到了ConnectionException

事务提交失败,因为事务已被标记为仅回滚。

有可能解决这个困境吗?

当然,我可以在创建新实体之前检查给定UUID的DeleteLogEntry是否存在。但由于这个问题只在罕见情况下发生,大多数时候检查会是负面的。当然,运行检查并不会对性能产生灾难性影响,但似乎并不是最好的解决方案。

有没有办法捕获异常并防止事务被标记为仅回滚?

1个回答

4

不,无法防止事务被标记。

Doctrine为postRemove启动了一个嵌套事务,如果它失败,就不应该提交其他事务。在这种情况下,将事务标记为回滚状态(甚至关闭实体管理器)是预期的行为,因为没有真正支持嵌套事务,因此没有其他方法可以确保一致性。

如果性能不是问题,则检查DeleteLogEntry是一个不错的选择。

其他可能的解决方案:

  • 暂时将ID存储在某个地方(Redis、Memcache、文件等),并在初始删除提交后更新DeleteLogEntry
  • 使用单独的实体管理器/连接来更新DeleteLogEntry
  • 删除唯一约束,并使用后台任务监视重复项

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接