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

我很难理解存储库模式。

关于这个主题有很多观点,比如在 储存库模式正确中,也有很多观点,比如在 仓库是新的 Singleton中,或者在 不要使用 DAO 使用存储库中,或者仅仅取 Spring JPA Data + Hibernate + MySQL + MAVEN,在这里,Repository 看起来与 DAO 对象相同。

我已经厌倦了阅读这些东西,因为这不可能是一件很难的事情,因为它显示在很多文章。

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

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

Service Layer获取 *DTO对象,并将这些对象传递给 Repository Layer,而 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与方法 ToolSetRepository.save(ToolSetDTO toolSetDto),“ 知道如何储存”一个 ToolSetDTO。但是几乎所有的教程都没有通过 *DTO而是通过了 Entity

这里困扰我的是,如果你以我的 ToolSet为例,我必须做以下步骤:

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

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

我想的是创建一个 ToolSetRepository但问题是

  • 它是接受一个 ToolSet实体对象还是使用一个 DTO对象?
  • 在任何情况下: *Repository是否允许 使用其他存储库对象?像当我想保存 ToolSet,但我必须存储 ToolToolDescription第一-我会使用 ToolRepositoryToolDescriptionRepository内的 ToolSetRepository?如果是这样: 为什么它不破坏存储库模式?如果这个模式基本上是服务和我的 ORM 框架之间的一个层,那么由于依赖关系的原因,将依赖关系添加到其他 *Repository类是不合适的。

我不知道为什么我就是想不明白。这听起来并不复杂,但仍然有像 Spring Data的帮助。另一件困扰我的事情是,因为我真的不明白这如何使 什么都行更容易。特别是因为我已经在使用 Hibernate 了——我看不出有什么好处(但也许这是另一个问题)。

So .. I know this is a long question but I put already a few days of research into it. There's already existing code I am working on right now that starts to become a mess because I just can't see through this pattern.

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

79371 次浏览

You can read my "repository for dummies" post to understand the simple principle of the repository. I think your problem is that you're working with DTOs and in that scenario, you don't really use the repository pattern, you're using a DAO.

The main difference between a repository and a dao is that a repository returns only objects that are understood by the calling layer. Most of the time the repository is used by the business layer and thus, it returns business objects. A dao returns data which might or might not be a whole business object i.e the data isn't a valid business concept.

If your business objects are just data structures, it might be a hint you have a modeling problem i.e bad design. A repository makes more sense with 'rich' or at least properly encapsulated objects. If you're just loading/saving data structures probably you don't need a repository the orm is enough.

If you're dealing with business objects that are composed from other objects (an aggregate) and that object needs all its parts in order to be consistent (an aggregate root) then the repository pattern is the best solution because it will abstract all persistence details. Your app will just ask for a 'Product' and the repository will return it as a whole, regardless of how many tables or queries are required to restore the object.

Based on your code sample, you don't have 'real' business objects. You have data structures used by Hibernate. A business object is designed based on business concepts and use cases. The repository makes it possible for the BL not to care about how that object is persisted. In a way, a repository acts as a 'converter/mapper' between the object and the model that will be persisted. Basically the repo 'reduces' the objects to the required for persistence data.

A business object is not a ORM entity.It might be from a technical point of view, but from a design pov , one models business stuff the other models persistence stuff. In many cases these are not directly compatible.

The biggest mistake is to design your business object according to storage needs and mindset. And contrary to what many devs believe, an ORM purpose is not to persist business objects. Its purpose is to simulate a 'oop' database on top of a rdbms. The ORM mapping is between your db objects and tables, not between app objects (even less when dealing with business objects) and tables.