存储库模式 - 如何理解它,它如何与“复杂”实体一起工作?

2022-08-31 12:10:00

我很难理解存储库模式。

关于这个主题有很多意见,比如在存储库模式中做得对,但其他东西,如存储库是新的单例,或者再次像不使用DAO使用存储库或只是采取Spring JPA Data + Hibernate + MySQL + MAVEN,其中存储库以某种方式看起来与DAO对象相同。

我厌倦了阅读这些东西,因为恕我直言,这不可能是一件困难的事情,因为它在很多文章中都有展示。

我是这样看的:看来我想要的是这样的东西:

         ------------------------------------------------------------------------
         |                            Server                                    |
         ------------------------------------------------------------------------
         |                    |                        |                        |
Client <-|-> Service Layer  <-|->  Repository Layer  <-|-> ORM / Database Layer |
         |                    |                        |                        |  
         ------------------------------------------------------------------------

获取对象并将这些对象传递给基本上只不过是知道如何存储实体的“家伙”。Service Layer*DTORepository Layer

例如,假设您有一些工具的组合(请注意,这只是伪代码)

@Entity
class ToolSet {
  @Id
  public Long id;
  @OneToOne
  public Tool tool1;
  @OneToOne
  public Tool tool2;
}

@Entity
class Tool {
  @Id
  public Long id;
  @OneToMany
  public ToolDescription toolDescription;
}

@Entity
class ToolDescription {
  @Id
  public Long id;
  @NotNull
  @OneToOne
  public Language language

  public String name;
  public String details;
}

我没有得到的是我从客户端获得对象的部分。ToolSetDTO

到目前为止,我所理解的,我可以用一个“知道如何存储”的方法编写一个.但几乎每个教程都不会通过,而是通过。ToolSetRepositoryToolSetRepository.save(ToolSetDTO toolSetDto)ToolSetDTO*DTOEntity

这里困扰我的是,如果你从上面举我的例子,我必须做以下步骤:ToolSet

  1. 如果不是,请采取并检查toolSetDtonull
  2. 对于a)拥有的每个
    ,如果具有有效的ID,则从转换为否则创建新的数据库条目
    b)并将其转换/保存到数据库或创建新条目tool*DtotoolSetDtoDTOEntitytoolDescriptionDto
  3. 在检查上述实例(实体)并将其设置为将其持久化到数据库中后ToolSet

所有这些都太复杂了,不能简单地让服务函数(客户端的接口)来处理这个问题。

我正在考虑的是创建例如a,但这里的问题是ToolSetRepository

  • 它是采用实体对象还是使用对象?ToolSetDTO
  • 无论如何:是否允许使用其他存储库对象?就像当我想保存,但我必须存储,首先 - 我会使用和里面吗?
    如果是这样:为什么它不会破坏存储库模式?如果这个模式基本上是服务和我的ORM框架之间的一个层,那么由于依赖性原因,向其他类添加依赖关系是“感觉不对的”。*RepositoryToolSetToolToolDescriptionToolRepositoryToolDescriptionRepositoryToolSetRepository*Repository

我不知道为什么我不能解决这个问题。这听起来并不那么复杂但仍然有帮助,比如.另一件困扰我的事情是,因为我真的不明白这如何使任何事情变得更容易。特别是因为我已经在使用Hibernate - 我没有看到好处(但也许这是另一个问题)。Spring Data

所以。。我知道这是一个很长的问题,但我已经花了几天时间研究它。我现在正在处理的已经存在的代码开始变得一团糟,因为我就是看不透这个模式。

我希望有人能给我一个比大多数文章和教程更大的图景,这些文章和教程除了实现一个非常非常简单的存储库模式示例之外。


答案 1

您可以阅读我的“傻瓜存储库”帖子,以了解存储库的简单原理。我认为你的问题是你正在使用DTO,在这种情况下,你并没有真正使用存储库模式,你正在使用DAO。

存储库和 dao 之间的主要区别在于,存储库仅返回调用层理解的对象。大多数情况下,存储库由业务层使用,因此,它会返回业务对象。dao 返回的数据可能是也可能不是整个业务对象,即数据不是有效的业务概念。

如果您的业务对象只是数据结构,则可能暗示您存在建模问题,即设计不良。存储库对于“丰富”或至少正确封装的对象更有意义。如果您只是加载/保存数据结构,则可能不需要存储库,orm就足够了。

如果您正在处理由其他对象(聚合)组成的业务对象,并且该对象需要其所有部分才能保持一致(聚合根),则存储库模式是最佳解决方案,因为它将抽象所有持久性细节。您的应用程序将只要求“产品”,存储库将将其作为一个整体返回,而不管还原对象需要多少表或查询。

根据代码示例,您没有“真实”的业务对象。您有 Hibernate 使用的数据结构。业务对象是基于业务概念和用例设计的。存储库使BL可以不关心该对象是如何持久化的。在某种程度上,存储库充当对象和将持久化的模型之间的“转换器/映射器”。基本上,存储库将对象“减少”为持久性数据所需的对象。

业务对象不是 ORM 实体。它可能是从技术角度来看的,但从设计的角度来看,一个模型业务的东西,另一个模型持久的东西。在许多情况下,这些不直接兼容。

最大的错误是根据存储需求和思维方式设计业务对象。与许多开发人员所认为的相反,ORM的目的不是持久化业务对象。其目的是在 rdbms 之上模拟“oop”数据库。ORM 映射是在数据库对象和表之间,而不是在应用程序对象(处理业务对象时更是如此)和表之间。


答案 2

推荐