存储库模式 - 如何理解它以及它如何与 "complex" 实体一起工作?
Repository Pattern - How to understand it and how does it work with "complex" entities?
我很难理解存储库模式。
关于该主题有很多意见,例如 Repository pattern done right but also other stuff like Repository is the new Singleton or again like in Don't use DAO use Repository or just take Spring JPA Data + Hibernate + MySQL + MAVEN 中,存储库在某种程度上似乎与 DAO 对象相同。
我已经厌倦了阅读这些东西,因为恕我直言,这不会像很多文章中显示的那样难。
我是这样看的:看来我想要的是这样的:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
Service Layer
获取 *DTO
对象并将这些对象传递给 Repository Layer
,后者基本上不过是 "the guy" 谁知道 如何 可以存储一个实体。
例如,假设您有一些工具的组合(请注意,这只是伪代码)
@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
示例,我必须执行以下步骤:
- 采取
toolSetDto
并检查是否null
- 对于
toolSetDto
拥有的每个 tool*Dto
a) 如果有一个有效的 id 然后从 DTO
转换为 Entity
否则创建一个新的数据库entry
b) toolDescriptionDto
and convert/save 它到数据库或创建一个新条目
- 在检查完上面的实例后
ToolSet
(实体)并将其设置为将其持久保存在数据库中
所有这些都太复杂了,不能简单地让服务函数(客户端接口)处理。
我当时想的是创造,例如a ToolSetRepository
但是这里的问题是
- 它采用
ToolSet
实体对象还是使用 DTO
对象?
- 无论如何:
*Repository
是否允许 使用 其他存储库对象?就像我想保存 ToolSet
但我必须先存储 Tool
和 ToolDescription
- 我会在 ToolSetRepository
中使用 ToolRepository
和 ToolDescriptionRepository
吗?
如果是这样:为什么它不破坏存储库模式?如果这个模式基本上是服务和我的 ORM 框架之间的一个层,它不会 "feel right" 将依赖添加到其他 *Repository
类 由于依赖原因。
我不知道为什么我无法理解这个问题。听起来 并不复杂,但仍然有像 Spring Data
这样的帮助。另一件事困扰着我,因为我真的不明白这如何使 anything 变得更容易。特别是因为我已经在使用 Hibernate - 我没有看到好处(但也许这是另一个问题)。
所以 .. 我知道这是一个很长的问题,但我已经对它进行了几天的研究。我现在正在处理的现有代码开始变得一团糟,因为我无法看穿这种模式。
我希望有人能给我比大多数文章和教程更全面的图景,这些文章和教程只是实现一个非常非常简单的存储库模式示例。
您可以阅读我的 "repository for dummies" post 以了解存储库的简单 原理 。我认为您的问题是您正在使用 DTO,在那种情况下,您并没有真正使用存储库模式,而是使用了 DAO。
存储库和 dao 之间的主要区别在于,存储库return只有调用层可以理解的对象。大多数时候,存储库由业务层使用,因此,它是 return 业务对象。 dao returns 数据可能是也可能不是整个业务对象,即数据不是有效的业务概念。
如果您的业务对象只是数据结构,则可能暗示您存在建模问题,即糟糕的设计。存储库对 'rich' 或至少正确封装的对象更有意义。如果您只是 loading/saving 数据结构,您可能不需要存储库,orm 就足够了。
如果您正在处理由其他对象(聚合)组成的业务对象,并且该对象需要其所有部分才能一致(聚合根)那么存储库模式是最好的解决方案,因为它将抽象所有持久性细节。您的应用程序将只请求 'Product',存储库将 return 作为一个整体,无论需要多少表或查询来恢复对象。
根据您的代码示例,您没有 'real' 个业务对象。你有 Hibernate 使用的数据结构。业务对象是根据业务概念和用例设计的。存储库使 BL 可以不关心该对象是如何持久化的。在某种程度上,存储库充当对象和将被持久化的模型之间的 'converter/mapper'。基本上 repo 'reduces' 持久性数据所需的对象。
业务对象不是ORM entity.It可能从技术的角度来看,但从设计的角度来看pov ,一个模型是业务模型,另一个模型是持久性模型。在许多情况下,这些并不直接兼容。
最大的错误是根据存储需求和思维方式设计业务对象。与许多开发人员的看法相反,ORM 的目的不是持久化业务对象。它的目的是在 rdbms 之上模拟一个 'oop' 数据库。 ORM 映射在您的数据库对象和表之间,而不是在应用程序对象(在处理业务对象时更不用说)和表之间。
我很难理解存储库模式。
关于该主题有很多意见,例如 Repository pattern done right but also other stuff like Repository is the new Singleton or again like in Don't use DAO use Repository or just take Spring JPA Data + Hibernate + MySQL + MAVEN 中,存储库在某种程度上似乎与 DAO 对象相同。
我已经厌倦了阅读这些东西,因为恕我直言,这不会像很多文章中显示的那样难。
我是这样看的:看来我想要的是这样的:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
Service Layer
获取 *DTO
对象并将这些对象传递给 Repository Layer
,后者基本上不过是 "the guy" 谁知道 如何 可以存储一个实体。
例如,假设您有一些工具的组合(请注意,这只是伪代码)
@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
示例,我必须执行以下步骤:
- 采取
toolSetDto
并检查是否null
- 对于
toolSetDto
拥有的每个tool*Dto
a) 如果有一个有效的 id 然后从DTO
转换为Entity
否则创建一个新的数据库entry
b)toolDescriptionDto
and convert/save 它到数据库或创建一个新条目 - 在检查完上面的实例后
ToolSet
(实体)并将其设置为将其持久保存在数据库中
所有这些都太复杂了,不能简单地让服务函数(客户端接口)处理。
我当时想的是创造,例如a ToolSetRepository
但是这里的问题是
- 它采用
ToolSet
实体对象还是使用DTO
对象? - 无论如何:
*Repository
是否允许 使用 其他存储库对象?就像我想保存ToolSet
但我必须先存储Tool
和ToolDescription
- 我会在ToolSetRepository
中使用ToolRepository
和ToolDescriptionRepository
吗?
如果是这样:为什么它不破坏存储库模式?如果这个模式基本上是服务和我的 ORM 框架之间的一个层,它不会 "feel right" 将依赖添加到其他*Repository
类 由于依赖原因。
我不知道为什么我无法理解这个问题。听起来 并不复杂,但仍然有像 Spring Data
这样的帮助。另一件事困扰着我,因为我真的不明白这如何使 anything 变得更容易。特别是因为我已经在使用 Hibernate - 我没有看到好处(但也许这是另一个问题)。
所以 .. 我知道这是一个很长的问题,但我已经对它进行了几天的研究。我现在正在处理的现有代码开始变得一团糟,因为我无法看穿这种模式。
我希望有人能给我比大多数文章和教程更全面的图景,这些文章和教程只是实现一个非常非常简单的存储库模式示例。
您可以阅读我的 "repository for dummies" post 以了解存储库的简单 原理 。我认为您的问题是您正在使用 DTO,在那种情况下,您并没有真正使用存储库模式,而是使用了 DAO。
存储库和 dao 之间的主要区别在于,存储库return只有调用层可以理解的对象。大多数时候,存储库由业务层使用,因此,它是 return 业务对象。 dao returns 数据可能是也可能不是整个业务对象,即数据不是有效的业务概念。
如果您的业务对象只是数据结构,则可能暗示您存在建模问题,即糟糕的设计。存储库对 'rich' 或至少正确封装的对象更有意义。如果您只是 loading/saving 数据结构,您可能不需要存储库,orm 就足够了。
如果您正在处理由其他对象(聚合)组成的业务对象,并且该对象需要其所有部分才能一致(聚合根)那么存储库模式是最好的解决方案,因为它将抽象所有持久性细节。您的应用程序将只请求 'Product',存储库将 return 作为一个整体,无论需要多少表或查询来恢复对象。
根据您的代码示例,您没有 'real' 个业务对象。你有 Hibernate 使用的数据结构。业务对象是根据业务概念和用例设计的。存储库使 BL 可以不关心该对象是如何持久化的。在某种程度上,存储库充当对象和将被持久化的模型之间的 'converter/mapper'。基本上 repo 'reduces' 持久性数据所需的对象。
业务对象不是ORM entity.It可能从技术的角度来看,但从设计的角度来看pov ,一个模型是业务模型,另一个模型是持久性模型。在许多情况下,这些并不直接兼容。
最大的错误是根据存储需求和思维方式设计业务对象。与许多开发人员的看法相反,ORM 的目的不是持久化业务对象。它的目的是在 rdbms 之上模拟一个 'oop' 数据库。 ORM 映射在您的数据库对象和表之间,而不是在应用程序对象(在处理业务对象时更不用说)和表之间。