Java 存储库模式 - 如何理解它以及它如何与“复杂”实体一起工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31305199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Repository Pattern - How to understand it and how does it work with "complex" entities?
提问by displayname
I'm having a hard time understanding the Repository Pattern.
我很难理解存储库模式。
There are a lot of opinions on that topic like in Repository pattern done rightbut also other stuff like Repository is the new Singletonor again like in Don't use DAO use Repositoryor just take Spring JPA Data + Hibernate + MySQL + MAVENwhere somehow a Repository appears to be the same as a DAO object.
关于这个话题有很多意见,比如在Repository 模式中做得对,但其他的东西,比如Repository 是新的 Singleton或者再次像Don't use DAO use Repository或者只是使用Spring JPA Data + Hibernate + MySQL + MAVEN不知何故Repository 似乎与 DAO 对象相同。
I'm getting tired of reading this stuff since imho this can't be such a hard thing as it is displayed in a lot of articles.
我已经厌倦了阅读这些东西,因为恕我直言,这并不是一件很难的事情,因为它在很多文章中都有体现。
I see it like this: It appears that what I want is something like this:
我是这样看的:看来我想要的是这样的:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
The Service Layer
takes *DTO
objects and passes those to the Repository Layer
that basically is nothing more than "the guy" who knows howan entity can be stored.
在Service Layer
需要*DTO
的对象,并将这些的Repository Layer
,基本上不外乎谁知道“的家伙”怎么一个实体可以存储。
For example assume you have a composition of some tools (please note that this is just pseudo code)
例如,假设您有一些工具的组合(请注意,这只是伪代码)
@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;
}
The thing I'm not getting is the part where I am getting a ToolSetDTO
object from the client.
我没有得到的是我ToolSetDTO
从客户端获取对象的部分。
As I understood it so far I could write a ToolSetRepository
with a method ToolSetRepository.save(ToolSetDTO toolSetDto)
that "knows how to store" a ToolSetDTO
. But almost every tutorial does not pass the *DTO
but the Entity
instead.
据我了解,到目前为止,我可以ToolSetRepository
使用ToolSetRepository.save(ToolSetDTO toolSetDto)
“知道如何存储” a的方法编写一个ToolSetDTO
. 但是几乎每个教程都没有通过,*DTO
而是Entity
相反。
What's bothering me here is that if you take my ToolSet
example from above I'd have to do the following steps:
在这里困扰我的是,如果你ToolSet
从上面看我的例子,我必须执行以下步骤:
- Take
toolSetDto
and check if notnull
- For each
tool*Dto
owned bytoolSetDto
a) If has a valid id then convert fromDTO
toEntity
otherwise create a new database entry
b)toolDescriptionDto
and convert/save it to the database or create a new entry - After checking those above instanciate
ToolSet
(entity) and set it up for persisting it in the database
- 拿去
toolSetDto
检查如果没有null
- 对于每个
tool*Dto
拥有的toolSetDto
a) 如果有一个有效的 id 则转换DTO
为Entity
否则创建一个新的数据库条目
b)toolDescriptionDto
并将其转换/保存到数据库或创建一个新条目 - 在检查上述实例化
ToolSet
(实体)并将其设置为将其保存在数据库中后
All this is too complex to simply let the service function (interface for the client) handle this.
所有这些都太复杂了,不能简单地让服务功能(客户端的接口)来处理。
What I was thinking about was creating e.g. a ToolSetRepository
but the question here is
我在想的是创建例如 aToolSetRepository
但这里的问题是
- Does it take a
ToolSet
entity object or does it use aDTO
object? - In any case: Is the
*Repository
allowed to useother repository objects? Like when I want to saveToolSet
but I have to storeTool
andToolDescription
first - would I useToolRepository
andToolDescriptionRepository
insideToolSetRepository
?
If so: Why doesn't it break the Repository Pattern? If this pattern is basically a layer between the service and my ORM framework it just does not "feel right" to add dependencies to other*Repository
classes due to dependency reasons.
- 它采用
ToolSet
实体对象还是使用DTO
对象? - 在任何情况下:是否
*Repository
允许使用其他存储库对象?就像当我要救ToolSet
,但我必须存储Tool
和ToolDescription
第一-我会用ToolRepository
和ToolDescriptionRepository
里面ToolSetRepository
?
如果是这样:为什么它不破坏存储库模式?如果这个模式基本上是服务和我的 ORM 框架之间的一个层,那么*Repository
由于依赖原因向其他类添加依赖是“感觉不对”的。
I don't know why I can't get my head around this. It does not sound thatcomplicated but there's still help out there like Spring Data
. Another thing that is bothering me since I really don't see how this makes anythingeasier. Especially since I'm using Hibernate already - I don't see the benefit (but maybe that's another question).
我不知道为什么我无法解决这个问题。这听起来并不那么复杂,但仍然有像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.
所以..我知道这是一个很长的问题,但我已经对其进行了几天的研究。我现在正在处理的现有代码开始变得一团糟,因为我无法看透这种模式。
I hope somebody can give me a bigger picture than most of the articles and tutorials which do not get beyond implementing a very, very simple example of a Repository Pattern.
我希望有人能给我一个比大多数文章和教程更大的图景,这些文章和教程不会超越实现一个非常非常简单的存储库模式示例。
采纳答案by MikeSW
You can read my "repository for dummies" postto understand the simple principleof 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.
您可以阅读我的“傻瓜存储库”帖子以了解存储库的简单原理。我认为您的问题是您正在使用 DTO,在这种情况下,您并没有真正使用存储库模式,而是使用了 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.
存储库和 dao 之间的主要区别在于存储库仅返回调用层理解的对象。大多数情况下,存储库由业务层使用,因此它返回业务对象。dao 返回的数据可能是也可能不是整个业务对象,即数据不是有效的业务概念。
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.
如果您的业务对象只是数据结构,则可能暗示您有建模问题,即糟糕的设计。存储库对于“丰富”或至少正确封装的对象更有意义。如果您只是加载/保存数据结构,则可能不需要存储库,orm 就足够了。
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.
根据您的代码示例,您没有“真正的”业务对象。您拥有 Hibernate 使用的数据结构。业务对象是基于业务概念和用例设计的。存储库使 BL 可以不关心该对象是如何持久化的。在某种程度上,存储库充当对象和将被持久化的模型之间的“转换器/映射器”。基本上,repo 将对象“减少”为持久性数据所需的对象。
A business object is nota ORM entity.It mightbe 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.
业务对象不是ORM 实体。它可能从技术角度来看,但从设计观点来看,一个建模业务内容,另一个建模持久性内容。在许多情况下,这些并不直接兼容。
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.
最大的错误是根据存储需求和思维方式设计业务对象。与许多开发人员所相信的相反,ORM 的目的不是持久化业务对象。它的目的是在 rdbms 之上模拟一个“oop”数据库。ORM 映射是在 db 对象和表之间,而不是在应用程序对象(在处理业务对象时更是如此)和表之间。