在mongodb中创建/持久化新文档



我正在使用doctrine-mongodb-odm-1.0.0-BETA10,并试图在preUpdate事件运行时提供一些基于InitialDocument的自定义逻辑。

假设InitialDocument获得了某种状态,该状态必须表现为新的StateDocument的初始状态。我正在做这样的事情:

class InitDocListener implements DoctrineCommonEventSubscriber {
    public function getSubscribedEvents()
    {
        return [
            Events::preUpdate
        ];
    }
    public function preUpdate($args){
        $document = $args->getDocument();
        if($document instanceOf InitialDocument && $document->getState() == 'mine'){
            $stateDocument = new StateDocument();
            $stateDocument->setInitDocument($document);
            $args->getDocumentManager()->persist($stateDocument);
            //no flush cause recursion happens
        }
    }
}
StateDocument

prePersist事件发生了,但它不会在db中持久化新文档。和postPersist事件将永远不会被触发。

还有一些自定义逻辑,但都在事件范围内。在某些情况下,逻辑可能会抛出一个异常,该异常必须停止InitialDocument的更新事件,因此InitialDocument的状态取决于StateDocument在业务范围内的创建过程。

我该如何解决这个问题?preFlush事件在changeSet重新计算之前运行不确定InitialDocument实例。所以在preFlush"搜索"更新是一种技巧,让我认为这是不正确的方式。请给我一个合适的建议。谢谢。

我在这里为您的用例创建了一个测试用例。从您的问题中的代码中脱颖而出的一件事是,您没有在生命周期回调期间修改的文档上调用recomputeSingleDocumentChangeSet(),正如preUpdate文档中提到的那样。但是即使调用了这个调用,新文档也不会被插入。这是因为UnitOfWork在插入和删除之后执行更新。完整的顺序可以在UnitOfWork的commit()方法中看到:

  • 文档插入
  • 文档插入
  • 文档更新
  • 额外更新(由持久类内部安排)
  • 收藏删除
  • 收集更新
  • 文档删除

preUpdate事件被调度时,对新文档的upserts/insert已经发生了。即使调用recomputeSingleDocumentChangeSet(),您最终也会调度插入文档,但UnitOfWork忽略了这一点,并在清除这里的所有调度队列时最终取消设置。

虽然一个简单的解决方案是让ODM在处理更新后检查是否有额外的插入,但在某些情况下,这可能会导致无限循环。UnitOfWork的排序早于我在项目上的工作,但是在构思最初的实现时,循环的风险可能是一个问题。

作为一种解决方法,您可能希望让侦听器转储要插入到其他容器(或侦听器本身)中的新文档,然后在事后检查是否有其他文档要持久化/刷新。

相关内容

  • 没有找到相关文章

最新更新