Nachdem ich Hibernate für die meisten meiner Projekte ungefähr 8 Jahre lang verwendet habe, bin ich bei einem Unternehmen gelandet, das von seiner Verwendung abrät und möchte, dass Anwendungen nur über gespeicherte Prozeduren mit der Datenbank interagieren.
Nachdem ich dies einige Wochen lang getan habe, konnte ich kein umfassendes Domänenmodell der Anwendung erstellen, die ich gerade erst zu erstellen beginne, und die Anwendung sieht nur aus wie ein (schreckliches) Transaktionsskript.
Einige der Probleme, die ich gefunden habe, sind:
- Das Objektdiagramm kann nicht navigiert werden, da die gespeicherten Prozeduren nur die minimale Datenmenge laden. Dies bedeutet, dass manchmal ähnliche Objekte mit unterschiedlichen Feldern vorhanden sind. Ein Beispiel ist: Wir haben eine gespeicherte Prozedur, um alle Daten von einem Kunden abzurufen, und eine andere, um Kontoinformationen sowie einige Felder vom Kunden abzurufen.
- Ein Großteil der Logik endet in Hilfsklassen, sodass der Code strukturierter wird (mit Entitäten, die als alte C-Strukturen verwendet werden).
- Langweiliger Gerüstcode, da es kein Framework gibt, das Ergebnismengen aus einer gespeicherten Prozedur extrahiert und in eine Entität einfügt.
Meine Fragen sind:
- Hat sich jemand in einer ähnlichen Situation befunden und war nicht mit der Vorgehensweise beim Laden einverstanden? was hast du getan?
- Gibt es einen tatsächlichen Vorteil bei der Verwendung gespeicherter Prozeduren? abgesehen von dem dummen Punkt "Niemand kann eine Drop-Tabelle ausstellen".
- Gibt es eine Möglichkeit, mithilfe gespeicherter Prozeduren eine Rich-Domain zu erstellen? Ich weiß, dass es die Möglichkeit gibt, mithilfe von AOP DAOs / Repositorys in Entitäten einzufügen, um im Objektdiagramm navigieren zu können. Ich mag diese Option nicht, da sie sehr nahe an Voodoo liegt.
Fazit
Zunächst einmal vielen Dank für Ihre Antworten. Die Schlussfolgerung, die ich gezogen habe, ist, dass ORMs nicht die Erstellung von Rich Domain-Modellen ermöglichen (wie einige Leute erwähnt haben), aber den Umfang der (oft wiederholten) Arbeit vereinfachen. Das Folgende ist eine detailliertere Erläuterung der Schlussfolgerung, basiert jedoch nicht auf harten Daten.
Die meisten Anwendungen fordern Informationen an und senden sie an andere Systeme. Dazu erstellen wir eine Abstraktion in den Modellbegriffen (z. B. ein Geschäftsereignis) und das Domänenmodell sendet oder empfängt das Ereignis. Das Ereignis benötigt normalerweise eine kleine Teilmenge an Informationen aus dem Modell, jedoch nicht das gesamte Modell. Beispielsweise fordert ein Zahlungsgateway in einem Online-Shop einige Benutzerinformationen und den Gesamtbetrag an, um einem Benutzer eine Gebühr in Rechnung zu stellen, benötigt jedoch nicht den Kaufverlauf, die verfügbaren Produkte und den gesamten Kundenstamm. Die Veranstaltung hat also einen kleinen und spezifischen Datensatz.
Wenn wir die Datenbank einer Anwendung als externes System verwenden, müssen wir eine Abstraktion erstellen, die es uns ermöglicht, die Domänenmodell- Entitäten der Datenbank zuzuordnen ( wie NimChimpsky erwähnt hat , unter Verwendung eines Daten-Mappers). Der offensichtliche Unterschied besteht darin, dass wir jetzt eine Zuordnung für jede Modellentität zur Datenbank (entweder ein Legacy-Schema oder gespeicherte Prozeduren) von Hand erstellen müssen, mit dem zusätzlichen Aufwand, dass eine Domänenentität teilweise zugeordnet werden kann, da die beiden nicht synchron sind einer Datenbankentität zugeordnet werden (z. B. wird eine UserCredentials-Klasse, die nur Benutzername und Kennwort enthält, einer Users-Tabelle mit anderen Spalten zugeordnet), oder eine Domänenmodellentität kann mehreren Datenbankentitäten zugeordnet werden (z. eine Zuordnung auf dem Tisch, aber wir wollen alle Daten in nur einer Klasse).
In einer Anwendung mit einigen wenigen Entitäten kann der zusätzliche Arbeitsaufwand gering sein, wenn die Entitäten nicht transversiert werden müssen. Er erhöht sich jedoch, wenn die Entitäten unter bestimmten Bedingungen transversiert werden müssen (und daher möchten wir möglicherweise eine Art 'Lazy' implementieren Wird geladen'). Mit zunehmender Anzahl von Entitäten in einer Anwendung nimmt diese Arbeit nur zu (und ich habe das Gefühl, dass sie nicht linear zunimmt). Ich gehe hier davon aus, dass wir nicht versuchen, ein ORM neu zu erfinden.
Ein Vorteil der Behandlung der Datenbank als externes System besteht darin, dass wir Situationen umgehen können, in denen zwei verschiedene Versionen einer Anwendung ausgeführt werden sollen, wobei jede Anwendung eine andere Zuordnung hat. Dies wird im Szenario kontinuierlicher Lieferungen an die Produktion interessanter ... aber ich denke, dass dies in geringerem Maße auch mit ORMs möglich ist.
Ich werde den Sicherheitsaspekt verwerfen, auf der Grundlage, dass ein Entwickler, auch wenn er keinen Zugriff auf die Datenbank hat, die meisten, wenn nicht alle in einem System gespeicherten Informationen erhalten kann, indem er bösartigen Code einfügt (z. B. Ich kann nicht glauben, dass ich vergessen habe, die Zeile zu entfernen, in der die Kreditkartendaten der Kunden vermerkt sind, sehr geehrter Herr! ).
Kleines Update (06.06.2012)
Gespeicherte Prozeduren (zumindest in Oracle) verhindern eine kontinuierliche Zustellung ohne Ausfallzeiten, da jede Änderung der Tabellenstruktur die Prozeduren und Trigger ungültig macht. Während der Aktualisierung der Datenbank ist die Anwendung daher ebenfalls inaktiv. Oracle bietet eine Lösung für diese Edition-Based Redefinition , aber die wenigen DBAs, die ich zu diesem Feature gefragt habe, erwähnten, dass es schlecht implementiert war und nicht in eine Produktions-DB aufgenommen werden würde.
Antworten:
Ihre Anwendung sollte weiterhin nach domänenbasierten Entwurfsprinzipien modelliert sein. Es sollte keine Rolle spielen, ob Sie ein ORM, eine direkte JDBC, aufrufende SPs (oder was auch immer) verwenden . Hoffentlich sollte in diesem Fall eine dünne Schicht, die Ihr Modell von den SPs abstrahiert, den Trick machen. Wie in einem anderen Poster angegeben , sollten Sie die SPs und ihre Ergebnisse als Service anzeigen und die Ergebnisse Ihrem Domain-Modell zuordnen.
quelle
In der Finanzwelt (und an Orten, an denen die Einhaltung von Sarbanes-Oxley erforderlich ist) müssen Sie in der Lage sein, Systeme zu überwachen, um sicherzustellen, dass sie das tun, was sie tun sollen. In diesen Fällen ist es viel einfacher, die Konformität sicherzustellen, wenn der gesamte Datenzugriff über gespeicherte Prozeduren erfolgt. Und wenn alles Ad-hoc-SQL entfernt wird, ist es viel schwieriger, Dinge zu verbergen. Als Beispiel, warum dies eine "gute Sache" wäre, verweise ich Sie auf Ken Thompsons klassisches Papier Reflections on Trusting Trust .
quelle
Gespeicherte Prozeduren sind sehr viel effizienter als clientseitiger SQL-Code. Sie kompilieren SQL in der DB vor, wodurch sie auch einige Optimierungen durchführen können.
In der Architektur gibt ein SP die minimalen Daten zurück, die für eine Aufgabe erforderlich sind. Dies bedeutet, dass weniger Daten übertragen werden. Wenn Sie über eine solche Architektur verfügen, müssen Sie sich die DB als einen Service vorstellen (stellen Sie sich einen Web-Service vor und jeder SP ist eine Methode zum Aufrufen). Es sollte kein Problem sein, mit diesen Daten zu arbeiten, während ein ORM Sie dazu anleitet, mit Remote-Daten wie mit lokalen Daten zu arbeiten, und Sie so dazu verleitet, Leistungsprobleme einzuführen, wenn Sie nicht aufpassen.
Ich war in Situationen, in denen wir SPs vollständig verwendet haben, die DB eine Daten-API bereitgestellt und wir haben sie verwendet. Diese spezielle App war sehr umfangreich und lief erstaunlich gut. Ich werde nichts schlechtes über SPs danach gesagt haben!
Ein weiterer Vorteil ist, dass die DBAs alle Ihre SQL-Abfragen für Sie schreiben und die gesamte relationale Hierarchie in der DB problemlos verarbeiten, sodass Sie dies nicht tun müssen.
quelle
the approach of letting the DBAs write the procedures smells like development silos
+100 Internet für dieses Juwel der Wahrheit. Ich habe dies immer als den Fall angesehen, in dem der Datenzugriff über gespeicherte Prozeduren gesteuert wurde.Was häufig passiert, ist, dass Entwickler ihre ORM-Objekte fälschlicherweise als Domänenmodelle verwenden.
Dies ist falsch und bindet Ihre Domain direkt an Ihr DB-Schema.
Was wirklich haben sollte, sind separate Domain-Modelle, die so umfangreich sind, wie Sie möchten, und die ORM-Ebene wird separat verwendet.
Dies bedeutet, dass Sie eine Zuordnung zwischen jedem Satz von Objekten benötigen.
quelle
Ihre Domain-Objekte können nach Belieben ausgefüllt werden. Die Verwendung von Hibernate ist nicht erforderlich. Ich denke, der richtige Begriff ist Data-Mapper . Es ist sehr wahrscheinlich, dass Ihre persistierten Daten eine völlig andere Struktur aufweisen als Ihre Domain-Objekte.
quelle