【问题标题】:How to autoflush in Doctrine 2?如何在 Doctrine 2 中自动刷新?
【发布时间】:2012-07-04 20:20:48
【问题描述】:

我正在使用 Doctrine 2,并希望此 ORM 在执行任何 SELECT 查询之前自动 flush() EntityManager,以确保应用程序内始终保持一致性(此应用程序抽象很多,不应该除了存储库之外,对 EntityManager 有任何了解)。

有没有使用 Doctrine 的选项?

如果没有,有什么策略可以轻松实现吗?

【问题讨论】:

  • 一个有趣的问题。我也想知道。
  • 构建服务,调用服务,构建查询。

标签: php orm doctrine-orm


【解决方案1】:

为什么需要在所有选择之前刷新(写入更改)?您是否可能需要事务一致性?即,插入/更新是否取决于先前选择的结果?在这种情况下,我建议使用显式事务,如下所示:

$em->transactional(function($em) {
    $entity = $em->find('Entity', 123);
    if ($entity->getValue() > 2)
    {
        $user = new User;
        $user->setName('George');
        $em->persist($user);
    }
});

如果没有,我建议坚持使用默认设置,让 unitOfWork 叠加并在运行时结束时优化插入/更新。

【讨论】:

  • 实际上恰恰相反。 SELECT 需要考虑在内存中修改的实体。但是这个选择被封装在一个存储库中,它本身被一个服务调用。 Service 做了很多非常抽象的工作,并且不能(阅读:应该不)处理诸如 EntityManager 之类的低级对象。 Hibernate 是启发 Doctrine 的 Java 开源 ORM,在事务处于活动状态时默认启用自动刷新。
  • “SELECT 需要考虑在内存中修改的实体” - 这听起来像您需要事务完整性。可以检查您的变更集并确定是否有任何与您所做的选择相关的事情。 $em->getUnitOfWork()->computeChangeSets(); $insertions = $em->getUnitOfWork()->getScheduledEntityInsertions();不知道这是否有任何帮助。
  • “在内存中修改”并不是指计划插入,而是指对现有实体的属性更改。无论如何,这与事务完整性无关,它与存储库没有在我的事务中返回陈旧数据有关。你提出的比我提出的要复杂,并没有解决问题(无意冒犯)!
  • 现有实体(托管)的属性更改将添加到工作单元更改集(作为更新),因此您仍然可以通过这种方式访问​​它。但是你的权利,它肯定会成为一个复杂的解决方案。
  • 实际上,我已经有了一个可行的解决方案:在我的每个 Repository 方法的开头调用flush()。因此更改将同步到数据库,查询结果将反映对象当前的内存状态。然而,这是一种容易出错的方法,我很乐意找到更通用的解决方案。
【解决方案2】:

到目前为止,我发现的唯一解决方案是在不得返回陈旧数据的存储库方法中发出SELECT 查询之前手动flush()

class OrderRepository
{
   public function findByUser(User $user)
    {
        $this->em->flush();

        $query = $this->em->createQuery( ... );

        // ...
    }
}

这样,刷新对使用存储库的服务隐藏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2012-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    相关资源
    最近更新 更多