【问题标题】:Is it OK to flush the EntityManager from within a domain Service?从域服务中刷新 EntityManager 是否可以?
【发布时间】:2013-03-23 12:33:19
【问题描述】:

我有一个名为OrderService 的域服务,带有saveOrder() 方法:

class OrderService
{
    // ...

    public function saveOrder(Order $order)
    {
        $this->orderRepository->add($order);
        // $this->entityManager->flush();

        $this->notificationService->notifyOrderPlaced($order);
    }
}

saveOrder() 将订单添加到存储库(在 EntityManager 上内部调用 persist()),然后将订单传递给 NotificationService 以发送适当的通知(电子邮件、短信)。

问题是,虽然 NotificationService 需要将订单 ID 包含在通知中,但订单还没有 ID,因为它没有被持久化到数据库中(ID 是自动生成的)。

显而易见的解决方案似乎将 EntityManager 作为依赖项传递给 OrderService,并在存储库 add() 方法之后立即传递 flush(),如上面的示例所示。但我一直不愿意让域服务了解 EntityManager,更愿意让它们只与存储库或其他服务通信。

  • 依赖于 EntityManager 的域服务有哪些缺点(如果有)?
  • 有更好的选择吗?

注意:我使用的是 PHP 和 Doctrine ORM,但我相信同样的原则也适用于 Java 和 Hibernate。

【问题讨论】:

  • 谁创建了Order?谁打电话给saveOrder()Order 是聚合根还是实体?这真的是域服务还是更多的应用层服务?
  • 控制器创建Order,控制器调用saveOrder()Order是聚合根,这是域服务。

标签: orm domain-driven-design entitymanager domainservices


【解决方案1】:

您可能需要考虑这些选项之一(或两者)

  • 将此服务设为应用层服务,而不是域服务。在应用程序服务中调用更改跟踪器是完全可以的,因为它应该知道当前用例中的应用程序上下文和进度。典型的应用程序服务将提交业务事务/要求更改跟踪器在完成后保存更改,所以why not call it to generate Id's 也是如此?

    如果您担心在用例中涉及数据库,也许您可​​以找到与 NHibernate 的 Guid.Comb strategy 等效的方法,以使您的 ORM 生成 Id 而无需立即向数据库发出 INSERT。

  • 使用域事件。在创建后,Order 可以通知世界它已被更新。通知服务将处理该事件并发送适当的通知。您会发现 here 的一个示例(它还包括一个应用层服务来处理业务事务)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-15
    • 1970-01-01
    • 2023-01-24
    • 1970-01-01
    相关资源
    最近更新 更多