Es fällt mir schwer, das Repository-Muster zu verstehen.
Es gibt viele Meinungen zu diesem Thema, wie in Repository-Muster richtig gemacht, aber auch andere Dinge wie Repository ist das neue Singleton oder wieder wie in DAO nicht verwenden Repository verwenden oder einfach Spring JPA Data + Hibernate + MySQL + MAVEN nehmen, wo irgendwie Ein Repository scheint mit einem DAO-Objekt identisch zu sein.
Ich werde es leid, dieses Zeug zu lesen, da dies imho nicht so schwer sein kann, wie es in vielen Artikeln gezeigt wird.
Ich sehe es so: Es scheint, dass ich so etwas will:
------------------------------------------------------------------------
| Server |
------------------------------------------------------------------------
| | | |
Client <-|-> Service Layer <-|-> Repository Layer <-|-> ORM / Database Layer |
| | | |
------------------------------------------------------------------------
Das Service Layer
nimmt *DTO
Objekte und gibt diese an den weiter Repository Layer
, der im Grunde nichts anderes als "der Typ" ist, der weiß, wie eine Entität gespeichert werden kann.
Angenommen, Sie haben eine Zusammensetzung einiger Tools ( bitte beachten Sie, dass dies nur Pseudocode ist ).
@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;
}
Das, was ich nicht bekomme, ist der Teil, in dem ich ein ToolSetDTO
Objekt vom Client bekomme .
So wie ich es bisher verstanden habe, konnte ich eine ToolSetRepository
mit einer Methode schreiben ToolSetRepository.save(ToolSetDTO toolSetDto)
, die " weiß, wie man speichert " ToolSetDTO
. Aber fast jedes Tutorial besteht nicht das, *DTO
sondern das Entity
.
Was mich hier stört, ist, dass ToolSet
ich die folgenden Schritte ausführen muss , wenn Sie mein Beispiel von oben nehmen :
- Nehmen Sie
toolSetDto
und überprüfen Sie, wenn nichtnull
- Für jedes
tool*Dto
Eigentum vontoolSetDto
a) Wenn es eine gültige ID hat, konvertieren Sie von,DTO
umEntity
andernfalls einen neuen Datenbankeintrag zu erstellen.
B)toolDescriptionDto
und konvertieren / speichern Sie es in die Datenbank oder erstellen Sie einen neuen Eintrag - Nachdem Sie die oben genannten Instanzen
ToolSet
(Entitäten) überprüft und eingerichtet haben, um sie in der Datenbank zu speichern
All dies ist zu komplex, um die Servicefunktion (Schnittstelle für den Client) einfach damit umgehen zu lassen.
Ich habe darüber nachgedacht, zB ein zu erschaffen, ToolSetRepository
aber die Frage hier ist
- Nimmt es ein
ToolSet
Entitätsobjekt oder verwendet es einDTO
Objekt? - Auf jeden Fall: Ist der
*Repository
zu dürfen verwenden andere Objekte Repository? Zum Beispiel,ToolSet
wenn ich speichern möchte, aber speichern mussTool
undToolDescription
zuerst - würde ich verwendenToolRepository
undToolDescriptionRepository
drinnenToolSetRepository
?
Wenn ja: Warum wird das Repository-Muster nicht beschädigt? Wenn dieses Muster im Grunde eine Schicht zwischen dem Dienst und meinem ORM-Framework ist, fühlt es sich aus Abhängigkeitsgründen einfach nicht "richtig" an, Abhängigkeiten zu anderen*Repository
Klassen hinzuzufügen .
Ich weiß nicht, warum ich das nicht verstehen kann. Es klingt nicht so kompliziert, aber es gibt immer noch Hilfe wie Spring Data
. Eine andere Sache, die mich stört, da ich wirklich nicht sehe, wie das etwas einfacher macht . Zumal ich Hibernate bereits verwende - ich sehe den Vorteil nicht (aber vielleicht ist das eine andere Frage).
Also ... ich weiß, dass dies eine lange Frage ist, aber ich habe bereits ein paar Tage lang darüber geforscht. Es gibt bereits Code, an dem ich gerade arbeite, der zu einem Chaos wird, weil ich dieses Muster einfach nicht durchschauen kann.
Ich hoffe, jemand kann mir ein größeres Bild geben als die meisten Artikel und Tutorials, die nicht über die Implementierung eines sehr, sehr einfachen Beispiels eines Repository-Musters hinausgehen.
quelle
ToolSetRepository
zum Beispiel mit der Persistenz vonTool
und umgehenToolDescription
? Von denen sollten diese schon bestehen geblieben sein? Wenn diese zu diesem Zeitpunkt bereits bestehen sollten, wo würde ich das dann tun? Dies in meiner Servicemethode zu tun, fühlt sich nicht richtig an, da komplexe Entitäten wieToolSet
den Servicemethodencode aufblähen würden. Imho eine Service-Methode sollte nur ein paar Initialisierungs- und grundlegende Überprüfungsarbeiten durchführen und dann die Arbeit an die nächste Ebene delegieren.Antworten:
Sie können meinen Beitrag "Repository für Dummies" lesen , um das einfache Prinzip des Repositorys zu verstehen . Ich denke, Ihr Problem ist, dass Sie mit DTOs arbeiten und in diesem Szenario das Repository-Muster nicht wirklich verwenden, sondern ein DAO.
Der Hauptunterschied zwischen einem Repository und einem Dao besteht darin, dass ein Repository nur Objekte zurückgibt , die von der aufrufenden Schicht verstanden werden . Meistens wird das Repository von der Geschäftsschicht verwendet und gibt daher Geschäftsobjekte zurück. Ein Dao gibt Daten zurück, die möglicherweise ein ganzes Geschäftsobjekt sind oder nicht, dh die Daten sind kein gültiges Geschäftskonzept.
Wenn Ihre Geschäftsobjekte nur Datenstrukturen sind, kann dies ein Hinweis darauf sein, dass Sie ein Modellierungsproblem haben, dh ein schlechtes Design. Ein Repository ist sinnvoller mit "reichen" oder zumindest richtig gekapselten Objekten. Wenn Sie nur Datenstrukturen laden / speichern, benötigen Sie wahrscheinlich kein Repository. Der Orm reicht aus.
Wenn Sie mit Geschäftsobjekten arbeiten, die aus anderen Objekten (einem Aggregat) bestehen und dieses Objekt alle seine Teile benötigt, um konsistent zu sein (ein Aggregatstamm), ist das Repository-Muster die beste Lösung, da es alle Persistenzdetails abstrahiert . Ihre App fragt nur nach einem "Produkt" und das Repository gibt es als Ganzes zurück, unabhängig davon, wie viele Tabellen oder Abfragen zum Wiederherstellen des Objekts erforderlich sind.
Basierend auf Ihrem Codebeispiel haben Sie keine "echten" Geschäftsobjekte. Sie haben Datenstrukturen, die von Hibernate verwendet werden. Ein Geschäftsobjekt basiert auf Geschäftskonzepten und Anwendungsfällen. Das Repository ermöglicht es dem BL, sich nicht darum zu kümmern, wie dieses Objekt beibehalten wird. In gewisser Weise fungiert ein Repository als "Konverter / Mapper" zwischen dem Objekt und dem Modell, das beibehalten wird. Grundsätzlich reduziert das Repo die Objekte auf die für Persistenzdaten erforderlichen Daten.
Ein Business - Objekt ist nicht ein ORM entity.It könnte aus technischen Sicht, sondern aus einem Entwurf pov, ein Geschäftsmodell Sachen der anderen Modellen Persistenz Zeug. In vielen Fällen sind diese nicht direkt kompatibel.
Der größte Fehler besteht darin, Ihr Geschäftsobjekt entsprechend den Speicheranforderungen und der Denkweise zu gestalten. Und im Gegensatz zu dem, was viele Entwickler glauben, besteht ein ORM-Zweck nicht darin, Geschäftsobjekte zu erhalten. Ihr Zweck ist es, eine 'oop'-Datenbank auf einem rdbms zu simulieren. Die ORM-Zuordnung erfolgt zwischen Ihren Datenbankobjekten und -tabellen, nicht zwischen App-Objekten (noch weniger beim Umgang mit Geschäftsobjekten) und Tabellen.
quelle
ToolSet
in der Datenbank speichern. Das heißt aber immer noch nicht, dass ich schreiben kann,ToolSetRepository
das im Grunde meine Entitätsklasse aufbaut und sie dann beibehält. Ist das richtig? Und ein letztes großes Problem, das ich in meiner Frage bekam, ist " Auf jeden Fall: Darf das*Repository
andere Repository-Objekte (darin) verwenden? ".