存储库模式 - 如何理解它以及它如何与"复杂"实体一起工作?

dis*_*ame 68 java spring hibernate repository-pattern

我很难理解存储库模式.

关于该主题有很多意见,比如在Repository模式中做得正确,但其他东西如Repository是新的Singleton或者再次像在不使用DAO使用Repository或只是采取Spring JPA Data + Hibernate + MySQL + MAVEN在某种程度上存储库看起来与DAO对象相同.

我已经厌倦了阅读这些东西,因为imho这不是一件很难的事情,因为它在很多文章中都有展示.

我觉得这样:似乎我想要的是这样的:

         ------------------------------------------------------------------------
         |                            Server                                    |
         ------------------------------------------------------------------------
         |                    |                        |                        |
Client <-|-> Service Layer  <-|->  Repository Layer  <-|-> ORM / Database Layer |
         |                    |                        |                        |  
         ------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

Service Layer需要*DTO的对象,并将这些的Repository 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;
}
Run Code Online (Sandbox Code Playgroud)

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

据我所知,到目前为止,我可以ToolSetRepository使用ToolSetRepository.save(ToolSetDTO toolSetDto)" 知道如何存储 "的方法编写一个ToolSetDTO.但几乎每个教程都没有通过,*DTO而是通过了Entity.

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

  1. toolSetDto并检查是否不null
  2. 对于每个tool*Dto拥有的toolSetDto
    a)如果有一个有效的id然后转换DTOEntity否则创建一个新的数据库条目
    b)toolDescriptionDto并将其转换/保存到数据库或创建一个新的条目
  3. 检查上面的instanciate ToolSet(实体)并将其设置为在数据库中持久保存

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

我在想的是创造一个ToolSetRepository但是这里的问题是

  • ToolSet实体对象还是使用DTO对象?
  • 在任何情况下:是否*Repository允许使用其他存储库对象?就像当我要救ToolSet,但我必须存储ToolToolDescription第一-我会用ToolRepositoryToolDescriptionRepository里面ToolSetRepository
    如果是这样:为什么不打破存储库模式?如果这个模式基本上是服务和我的ORM框架之间的一个层,那么*Repository由于依赖性原因,它只是"感觉正确"将依赖关系添加到其他类.

我不知道为什么我无法理解这一点.这听起来并不认为复杂,但还是有帮助有像Spring Data.另一件困扰我的事情是因为我真的不知道这会让事情变得更轻松.特别是因为我已经使用了Hibernate - 我没有看到好处(但也许这是另一个问题).

所以..我知道这是一个很长的问题,但我已经进行了几天的研究.现在已经存在的代码已经开始变得一团糟,因为我无法看清这种模式.

我希望有人能给我一个比大多数文章和教程更大的图片,这些文章和教程不会超出实现一个非常非常简单的存储库模式的例子.

Mik*_*eSW 91

您可以阅读我的"dummies存储库" 帖子,以了解存储库的简单原则.我认为你的问题是你正在使用DTO,在那种情况下,你并没有真正使用存储库模式,你正在使用DAO.

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

如果您的业务对象只是数据结构,那么可能暗示您存在建模问题,即设计错误.使用"丰富"或至少正确封装的对象,存储库更有意义.如果您只是加载/保存数据结构,可能您不需要存储库,orm就足够了.

如果您正在处理由其他对象(聚合)组成的业务对象,并且该对象需要其所有部分以保持一致(聚合根),那么存储库模式是最佳解决方案,因为它将抽象所有持久性详细信息.您的应用程序将只询问"产品",并且存储库将作为一个整体返回它,无论还原对象需要多少表或查询.

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

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

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

  • @StefanFalk存储库模式实际上是接口**的**设计.一旦你有了界面,你可以疯狂地实际实现.关于使用其他存储库的存储库,我认为不是,这是错误的设计,这意味着你有2个repos处理相同的对象.但是存储库可以使用很多DAO.在我的代码库中,repos不了解彼此.事实上,你需要有一个合适的商业模式(具有明确的一致性边界)才能正确使用存储库,否则它只是一个复杂的问题. (4认同)
  • 顺便说一句,存储库的目的是存储/检索东西.东西越复杂越好.但请记住重要的一点:该对象必须代表一个商业**概念**简单(一个结构)或复杂(许多规则或许多孩子). (3认同)