【问题标题】:Best practice of designing JPARepository(ies) for ORM Domain graph为 ORM 域图设计 JPARepository(ies) 的最佳实践
【发布时间】:2017-07-25 14:52:11
【问题描述】:

我一直在使用标准 MVC 架构设计 spring rest api,例如域层作为 POJO 和存储库,以从 db 表中获取域数据。到目前为止,这些实体是隔离的,因此设计充当了每个实体的独立 RestController、Service 和 Repository 流。 当涉及到域对象(即 ORM)中的关联时,我一直在寻求了解最佳实践。例如,让我们用下面的伪代码来说明领域类(只是为了表达有问题的设计。我没有提供完整的类):

public class Customer {
    @Column
    private int id;

    @Column;
    private String name;

    @OneToMany
    private List<Order> orders;

    //...getters setters
}

public class Order {
    @Column
    private int id;

    @Column;
    private String orderNumber;

    @OneToMany
    private List<Product> products;

    @ManyToOne
    private Customer customer;

    //...getters setters
}

 public class Product {
    @Column
    private int id;

    @Column;
    private String productName;

    @ManyToOne
    private Order order;

    //...getters setters
}

从设计的角度来看,我的困境。我有以下方法,很可能都是不正确的:

  1. 为客户定义一个 RestController 并提供所有 api 资源,如 /customers、/customers/id/orders、/customers/id/orders/id/products 等。拥有一项服务来处理这些资源域。每个域都有单独的 JPARepository。这里的“保持简单”是我为每个域都有单独的存储库,因此我只需要在相应的存储库类中提供查询方法即可查找特定域的详细信息,即获取给定客户 ID 的订单。然而,这让我觉得扼杀了使用 ORM 模型的目的,因为我正在通过它们的 Repository 类获取各个域。此选项将使所有 3 个存储库类都连接到服务类中,我认为这也不是一个好的设计。 3 在这里看起来不错,但在我的实际需求中,我在 ORM 图中有 6 到 7 个域,这意味着在一个服务类中自动装配 6 个存储库。

  2. 一个 RestController 和一个 Service 类,如上述选项,但 Repository 类也是单一的。存储库仅为客户域创建。通过这种方式,我检索了其他域延迟加载的客户。这是为了满足“/customers”的 GET 请求。为了满足“/customers/id/orders”的 GET 请求,我将再次使用客户存储库,检索给定 ID 的客户,然后返回订单列表。此外,对于 "/customers/id/orders/id/products" 的 GET 请求,我将需要在 Customer 域中编写手动数据获取机制,以便它负责检索给定 customerId 和 orderId 的产品列表。这样我使用一个存储库,满足使用 ORM 的目的,然后在客户域中添加手动获取数据的方法。我看到的另一个负面影响是,即使我有可用的 customerId 和 orderId,我也需要获取客户域中的完整订单列表。如果我为 Order 使用了单独的存储库,我会根据 customerId 和 orderId 获取一个订单。

  3. 两者都不正确,存在更好的方法。

我查看了 spring docs 的存储库和 ORM 的休眠文档。我浏览了多个教程,用于使用 Spring Data Rest 进行一对多映射,但我在不同的教程中发现了混合方法。

这个问题对您来说似乎是重复的,因为我已经阅读了有关此设计问题的多篇关于 stackoverflow 的帖子,但没有一个答案可以让我对上面提到的权衡和选项进行推理。因此,我重新发布这个问题。

【问题讨论】:

    标签: java spring hibernate jpa


    【解决方案1】:

    这是一种混合方法。例如在您的情况下,产品实体不需要与订单有 @ManyToOne 关系。想象一下,如果您的产品是 100 万份订单的一部分!您将查询产品多少次才能找到订单?您将查询 findOrdersByProduct(Product) 而不是 findProductByOrder(Order)

    1. 想想你的用例。有时,如果您永远不会从关系所有者那里获取信息,那么拥有一个方向映射是有意义的

    2. 考虑查询实体时将获取的数据量(包括连接)。

    3. 例如,如果我要获取一个组织,我是否需要获取其所有员工?您的系统会折腾(延迟加载将节省您大部分时间,但如果您有 Angular,那么它将绑定并获取整个模型)。但是,与员工实体的组织建立多对一关系确实有意义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-03
      • 2016-05-19
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      • 2013-07-31
      相关资源
      最近更新 更多