Was ist der beste Ansatz, wenn Sie Modellobjekte aus mehreren Datenquellen ziehen?
Zum Beispiel habe ich eine Anwendung hat einige Daten in einer MySQL-Datenbank mit Hibernate gespeichert. Was, wenn ich einige andere Objekte in EC2 oder Google App Engine speichern möchte? Ich verstehe, dass DAO die Implementierung der Arbeit mit einer bestimmten Datenquelle abstrahiert, aber was ist mit den Entitäten selbst?
Zuerst dachte ich, meine Entitäten mit jpa Annotationen zu kommentieren wäre eine großartige Lösung, aber jetzt scheint es, als hätte ich meine Entitäten wirklich an eine bestimmte Implementierung gebunden. Im Fall von App Engine zum Beispiel machen einige dieser Anmerkungen keinen Sinn.
Es scheint, als ob ich eine reine POJO-Klasse brauche, um meine Entitäten darzustellen, völlig frei von Persistenzlogik. Wenn ich zum Beispiel einen Hund modellieren wollte (ja, lahme Wahl, aber was auch immer).
Wäre es sinnvoll, eine abstrakte Hundeklasse zu haben, dann definieren Sie Unterklassen, um mit bestimmten Persistenzlösungen zu arbeiten: HibernateDog, GAEDog, usw.
Danke.
Das ist eine großartige Frage, auch wenn das Problem nicht neu ist. Als Industrie haben wir das "konventionelle Wissen" zu diesem Thema häufig über die Jahre verändert. Die Antworten, die Sie heute erhalten, sind nicht unbedingt die, die Sie vor 5 Jahren oder 5 Jahren in der Zukunft bekommen würden.
Wenn ich mir vorstelle, wie ich gerne mit diesem Gegenstand umgehen würde, frage ich mich über einige Dinge, die Sie nicht gesagt haben: Ist Ihre App das "System der Aufzeichnung" für Hundemächte? Was andere Subsysteme / Layer / Apps über Dog-Entitäten wissen müssen.
Wenn Sie in Java brandneue Typen wie Animal & gt; Hund, du bekommst folgende Belohnung: die Möglichkeit, einen ganzen Haufen mehr Code zu schreiben, der weiß, wie man mit Tierobjekten und Hundobjekten interagiert. 2010 bin ich weniger überzeugt, dass dies eine gute Idee ist, als ich vor fünf Jahren war.
Sind Sie für die Gestaltung der Datenbank verantwortlich, in der die Hundeinformationen gespeichert sind? Das haben wir die ganze Zeit gemacht, aber heutzutage finde ich mich normalerweise mit Datensätzen, die tatsächlich von anderen Systemen verwaltet werden: google APIs, LDAP Entitäten, Data Warehouses, Produkte wie peoplesoft, etc.
Wenn Sie nicht damit beschäftigt sind, zu definieren, was ein Hund ist und wie er mit dem Universum interagiert, würde ich mir eine domänenunabhängige Methode ansehen, um Dog-Informationen im Speicher zu modellieren. Es gibt Tonnen: XML / DOM, JSON, Karte, etc.
Die Vorteile, Daten anderer Leute in diesen Formaten zu bewegen, sind viele ...
Auf der anderen Seite ... Wenn Sie das System der Aufzeichnung für Dog-Daten sind, sollten Sie die Verwendung von Schnittstellen anstelle von abstrakten Klassen in Erwägung ziehen. Oder vielleicht Schnittstellen und abstrakte Klassen. Java hat nur eine einzige Vererbung; binden Sie Ihren View / Controller / anderen Code an Schnittstellen, um die Flexibilität der Zukunft zu gewährleisten.
Eines der Probleme mit Hibernate ist, dass es eigene Collection
-Implementierungen in Ihre Domänenklasse einfügt, was zu Problemen führt, wenn Sie versuchen, Ihre Klasse mithilfe der Serialisierung über die Leitung zu senden (z. B. von Server zu Client).
In Ihrem obigen Beispiel würde ich die Notwendigkeit infrage stellen, speicherspezifische Unterklassen bereitzustellen:
Tun / Sollten die Klassen wirklich einen Zustand enthalten, der mit der Art und Weise zusammenhängt, in der sie gespeichert wurden? Ist das ein zentraler Begriff für die Klasse und daher wert, den "One-Shot" bei der Vererbung (in Java) zu verwenden? Ich würde argumentieren, dass eine nützlichere Vererbungshierarchie in Ihrem Beispiel etwa so aussehen würde:
Außerdem können Sie beim vorgeschlagenen Design Probleme bekommen, wenn Sie beispielsweise eine Dog
-Instanz in Hibernate speichern möchten, aber nicht wissen, ob Dog
ein HibernateDog
, GAEDog
ist. usw. und müssen an dieser Stelle Checks / Downcasts durchführen.
JPA-Anmerkungen können insofern nützlich sein, als sie Ihnen erlauben, Ihre ORM-Metadaten (Object-Relational Mapping) in denselben Dateien wie Ihre Entitätsklassen zu platzieren, aber Sie haben absolut Recht, dass Bedenken bei der Kombination von JPA-Metadaten bestehen mit "reinen" POJOs. Es ist ein Kompromiss.
Es gibt jedoch eine Alternative. Sie können die ORM-Konfiguration in XML-Dateien externalisieren und auf diese Weise diese Details aus Ihren Entitätsklassen heraushalten. JPA bietet eine XML-Konfigurationssyntax, aber für meine Projekte bevorzuge ich native Hibernate-XML-Mappings für die zusätzliche Flexibilität, die sie bieten. Es mag nicht so modisch sein wie ein Annotations-Ansatz, aber meiner Erfahrung nach funktioniert es ziemlich gut.
Sie verwenden eine DAO-Ebene, um die Datenquellendetails von anderen Layern zu abstrahieren. Daher sollte der Modell-Layer eigentlich keine Kenntnis darüber haben, welche Datenspeichertechnik oder welche Datenbank verwendet wird.
Die Antwort auf Ihre Frage lautet: Verwenden Sie die Serviceebene. Auf dieser Ebene legen Sie Ihren gesamten Geschäftscode ab. Welche Entität wird instanziiert, welche DAO verwendet, wie werden Daten, Transaktionsabgrenzung usw. bestätigt?
Die Service-Schicht sollte also in der Lage sein, Ihre Entitäten zu laden / persistieren. Und hier sollten Sie die Logik einbetten, welche Datenquelle / Datenbank verwendet werden soll. Verwenden Sie die Abhängigkeitsinjektion von Spring, um Ihnen dabei zu helfen. Injizieren Sie Ihre Auswahl der DAOs, Entities in die Service-Schicht.
Entitätsklassen: Hund, Katze
Serviceklassen: AnimalCenterService
DAO-Klassen: AnimalCenterHibernate, AnimalCenterJDBC
Lassen Sie es mich wissen, wenn mehr Erklärungen benötigt werden. Nur meine 2 Cent
Was Sie haben, scheint der richtige Weg zu sein. Guter Entwurf bedeutet nicht, dass Entitäten nicht an eine Technologie gebunden sind, sondern bedeutet nur, dass Sie nur eine Ebene Ihrer App ändern, wenn Sie die Technologie ändern.
Entitäten mit JPA sind eine gute Lösung, wenn Sie JPA verwenden. Neben diesen Entitäten können Sie mehr "Entitäten" (POJOs) haben, die mit GAE usw. verbunden sind.
Über den abstrakten Hund und die Unterklassen scheint das ein Overkill zu sein, außer wenn es wirklich, wirklich nötig ist. Wenn Sie wirklich brauchen, überprüfen Sie bitte DTO-Objekte: Ссылка
DTOs werden verwendet, um das Objekt konsistent in höhere Ebenen (über DAO) zu übertragen (und es serialisierbar zu machen), selbst wenn es sich um mehrere Datenquellen / Technologien in der Persistenzschicht handelt.
Sie möchten nicht, dass Ihr persistenzspezifischer Code von Ihren Entitätsklassen übernommen wird, da dies die Verwendung der Vererbung für Ihre Domänenentitätsklassen unmöglich machen würde. Wenn Sie zum Beispiel HibernateDog von Dog geerbt haben, ist es nicht erlaubt, dass Poodle von Dog erbt, ohne dass Pudel Hibernate-spezifisch wird.
Ein Ansatz, der funktioniert, ist die Verwendung von Dateneinheiten, die Persistenz-spezifisch sind. Ihre Domänenentitätsklassen würden über eine Schnittstelle an das Datenentitätsobjekt für seine persistenten Attribute delegieren. Sie könnten dann verschiedene persistente implementierungsspezifische Datenentitätsklassen ersetzen, solange sie Ihrer Datenentitätsschnittstelle entsprechen.
Dog-Referenzen (und Delegaten an) DogEntity-Schnittstelle. Poodle erbt von Dog, PodeEntity erbt von DogEntity.
HibernateDog implementiert DogEntity
HibernatePoodle implementiert PoodleEntity und erbt von HibernateDog.
...
StubDog implementiert DogEntity
StubPoodle implementiert PoodleEntity und erbt von StubDog
...
Sie können beliebig viele Datenelementtypen verwenden. Die Dateneinheiten wären sehr dünn und würden nur die persistenten Elementvariablen und die Anmerkungen oder irgendeinen anderen Code enthalten, der für die Persistenz erforderlich ist.
Die Domänen-Entitäten enthalten die Entitäts-spezifische Geschäftslogik.
Tags und Links java design-patterns model entity