当我们只有他们的身份来时,我一直在寻找正确的方法来引用聚合根中的实体来自URL参数。我问previous question最后关注值对象,所以我从这里开始另一个例子。
假设我们要修改OrderLine
内的Order
:
edit-order-line?orderId=x&orderLineId=y
现在,如果我需要更新OrderLine中的数量,我可以这样做:
Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);
但是,我对将责任留给订单以便通过Id检索部分内容的想法感到不自在。我对这个主题的看法是,在域内,我们应该与对象交谈,而不是与Ids交谈。 Ids不是无所不在的语言的一部分,我相信它们应该存在于域之外,例如在Controller中。
我会对以下内容更有信心:
Order order = orderRepository.find(orderId);
OrderLine orderLine = em.find(OrderLine.class, orderLineId);
order.updateQuantity(orderLine, 2);
虽然我不喜欢直接与实体管理器交互的想法。我觉得我绕过了Repository和Aggregate Root职责(因为我可以,可能直接与OrderLine交互)。
你如何解决这个问题?
答案 0 :(得分:12)
在我看来,这种方法没有错:
Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);
orderLineId
是“本地身份”。它特定于聚合根,并且在它之外没有意义。您不必将其称为“id”,它可以是“订单行号”。来自Eric Evan's书:
边界内的ENTITIES具有本地身份,仅在其中具有唯一性 AGGREGATE。
...只有AGGREGATE根可以直接使用数据库查询获得。必须通过遍历关联找到所有其他对象。
答案 1 :(得分:1)
OrderLineId究竟是什么?它毫无意义。您正在更新PRODUCT的数量,以及应该用作ID的内容。
Order order = orderRepository.find(orderID);
order.updateQuantity(productID, 2);
答案 2 :(得分:0)
聚合根绑定到上下文,在您的上下文中,订单 AR,因此可以直接更新它,因为您直接公开它,如果该代码影响他们应该在订单AR中居住的其他实体。
如果你想要更纯粹的方法,你必须在AR中创建一个findByOrderId并完全加载它或在你的应用程序中公开OrderLine和OrderId(然后使用你的第二种方法)。