【问题标题】:Saving Aggregate Roots without exposing nested Entities保存聚合根而不暴露嵌套实体
【发布时间】:2014-08-27 18:20:48
【问题描述】:

假设我有以下聚合根:

class Order {
     private Collection<OrderItem> items;
     ...
     public void updateQuantity(int itemId, int quantity) { ... }
}

假设我使用纯 SQL 来持久化它。问题是:如何在不暴露集合的情况下保留 Order 及其项目?我看到了几种我不喜欢的方式:

1) 添加一个返回复制集合的方法。我不喜欢它,因为我们还需要复制每个项目(因为它是实体并且可以更改),这本身就是另一个挑战。

2) 为项目的每个属性添加 getter:

 class Order {
      public int getQuantity(int itemId) { ... }
 }

这样更好,因为外部没有人不能更改根的嵌套实体。但是它可以用大量的虚拟吸气剂来破坏根类。

3) 使用Hibernate方式:通过java在repository中的反射获取item。那是作弊”。我也在考虑创建 DTO 的方式,所以我需要一种合法的方式来读取这些值。

4) 使该字段使用默认修饰符并将存储库实现(以及 DTO 的汇编器)放入同一个包中,以便它可以访问这些字段。不喜欢它,因为存储库实现不是域的一部分。

我更喜欢第二种方法,但我可能还缺少其他方法?

【问题讨论】:

    标签: java hibernate persistence domain-driven-design aggregate


    【解决方案1】:

    我会公开OrderItems 的集合。

    有一个很好的SO question "What is the best practice for read-only lists in NHibernate",在那里你可以找到很多如何正确公开集合的信息。

    我认为将OrderItems 的集合隐藏为内部状态没有任何顾虑。如果您公开updateQuantity 方法,那么应该有可能检查特定项目的数量是否更新。

    1) 添加一个返回复制集合的方法。我不喜欢, 因为我们还需要复制每个项目(因为它是 实体并且可以更改)这本身就是另一个挑战。

    实际上,实体是可以更改的,它们不是一成不变的。值对象应该是不可变的。

    在你的例子中Orderlooks like root entity or Aggregate Root and OrderItem looks like Entity. It has an identity within an Order at least so it is definitely not a Value Object.

    3) 使用Hibernate方式:通过java中的反射获取item 存储库。那是作弊”。我也在想办法 还要创建 DTO,所以我需要一种合法的方式来读取这些值。

    有些人使用两种模型:

    • “干净”领域模型
    • 和“依赖于脏数据库”的持久性模型。

    好吧,我不是这种方法的忠实拥护者。通常我会尝试让我的 ORM 基于域模型生成体面的数据库结构。

    2) 为项目的每个属性添加 getter:

    这样更好,因为外面没有人不能改变根的嵌套 实体。但是它可以用大量的虚拟吸气剂来破坏根类。

    为了防止它们受到外部更改最好不要暴露public setter,至少要保留privateprotected

    【讨论】:

    • 顺便说一句,OrderItem 是可变的,但我希望它只能通过根进行更改。
    • 它可以是可变的,但访问修饰符可以限制它在其他层的客户端(例如表示)
    猜你喜欢
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多