java - 存储库模式 - 如何理解它以及它如何与 "complex"实体一起使用?

标签 java spring hibernate repository-pattern

我很难理解存储库模式。

关于这个话题有很多意见,比如 Repository pattern done right还有其他的东西,比如 Repository is the new Singleton或再次像 Don't use DAO use Repository或者就拿Spring JPA Data + Hibernate + MySQL + MAVEN不知何故,存储库似乎与 DAO 对象相同。

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

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

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

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;
}

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

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

这里困扰我的是,如果您从上面的 ToolSet 示例中获取我必须执行以下步骤:

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

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

我在想的是创建例如ToolSetRepository 但这里的问题是

  • 是使用 ToolSet 实体对象还是使用 DTO 对象?
  • 无论如何:*Repository 是否允许使用 其他存储库对象?就像我想保存 ToolSet 但我必须先存储 ToolToolDescription - 我会使用 ToolRepositoryToolDescriptionRepositoryToolSetRepository 内?
    如果是这样:为什么它不破坏存储库模式?如果这种模式基本上是服务和我的 ORM 框架之间的一个层,那么由于依赖原因,它只是不“感觉正确”向其他 *Repository 类添加依赖项。

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

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

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

最佳答案

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

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

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

如果您正在处理由其他对象(聚合)组成的业务对象,并且该对象需要其所有部分才能一致(聚合根),那么存储库模式是最好的解决方案,因为它将抽象所有持久性细节。您的应用将只请求一个“产品”,并且存储库会将其作为一个整体返回,无论需要多少表或查询来恢复对象。

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

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

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

关于java - 存储库模式 - 如何理解它以及它如何与 "complex"实体一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31305199/

相关文章:

java - 为桌面应用程序进行连接池有意义吗?

java - CrudRepository 生成了一个困惑的 Sql 请求

java - 你能告诉我,我的请求映射有什么问题吗?

java.lang.IllegalStateException : Neither BindingResult nor plain target object for bean name 'login' available as request attribute

java - 从 HDD 或 OS 缓冲区缓存或 RAM DISK 读取文件所需的时间几乎相同

java - 将所有逻辑表达式变量放入数组中

java - Hibernate FETCH.Eager 在使用 Spring Data 存储库时获取重复项

java - 如何使用具有相同存储库的多种数据源类型?

hibernate - Solr 与 Hibernate 搜索 - 选择哪个以及何时选择?

java - 如何使 java 准备语句像大查询的查询或如何在大查询中转义参数