Wo sollte eine JDBC-kompatible Anwendung ihre SQL-Anweisungen speichern und warum?
Bisher konnte ich folgende Optionen identifizieren:
- In Geschäftsobjekten fest codiert
- Eingebettet in SQLJ Klauseln
- In getrennten Klassen einkapseln, z Datenzugriffsobjekte
- Metadatengesteuert (entkoppeln Sie das Objektschema vom Datenschema - beschreiben Sie die Zuordnungen zwischen ihnen in Metadaten)
- Externe Dateien (z. B. Eigenschaften- oder Ressourcendateien)
- Gespeicherte Prozeduren
Was sind die Vor- und Nachteile für jeden einzelnen?
Sollte SQL-Code als "Code" oder "Metadaten" betrachtet werden?
Sollten gespeicherte Prozeduren nur zur Leistungsoptimierung verwendet werden oder sind sie eine legitime Abstraktion der Datenbankstruktur?
Ist Leistung ein Schlüsselfaktor für die Entscheidung? Was ist mit der Lieferantenbindung ?
Was ist besser - lose oder enge Kupplung und warum?
EDITED: Vielen Dank an alle für die Antworten - hier ist eine Zusammenfassung:
Metadatengesteuert, dh Object Relational Mappings (ORM)
Vorteile:
- Sehr abstrakt - Der DB-Server kann gewechselt werden, ohne dass das Modell geändert werden muss
- Weit verbreitet - praktisch ein Standard
- Reduziert die Menge an benötigtem SQL
- Kann SQL in Ressourcendateien speichern
- Leistung ist (normalerweise) akzeptabel
- Metadatengetriebener Ansatz
- Herstellerunabhängigkeit (Datenbank)
Nachteile:
- Versteckt SQL und echte Entwicklerabsichten
- SQL kann vom DBA nur schwer überprüft / geändert werden
- In ungeraden Fällen wird möglicherweise noch SQL benötigt
- Kann die Verwendung einer proprietären Abfragesprache erzwingen, z. B. HQL
- Geeignet nicht zur Optimierung (Abstraktion)
- Kann referenzielle Integrität fehlen
- Ersatz für mangelnde SQL-Kenntnisse oder mangelnde Sorgfalt beim Codieren in der Datenbank
- Passen Sie niemals die native Datenbankleistung an (auch wenn sie nahe kommt).
- Der Modellcode ist sehr eng mit dem Datenbankmodell gekoppelt
Hardcodiert / eingekapselt in DAO-Schicht
Vorteile:
- SQL wird in den Objekten gespeichert, die auf Daten zugreifen (Kapselung)
- SQL ist einfach zu schreiben (Entwicklungsgeschwindigkeit)
- SQL ist leicht zu finden, wenn Änderungen erforderlich sind
- Einfache Lösung (keine chaotische Architektur)
Nachteile:
- SQL kann vom DBA nicht überprüft / geändert werden
- SQL wird wahrscheinlich DB-spezifisch
- SQL kann schwer zu warten sein
Gespeicherte Prozeduren
Vorteile:
- SQL in der Datenbank gespeichert (in der Nähe von Daten)
- SQL wird vom DBMS analysiert, kompiliert und optimiert
- SQL kann von DBA leicht überprüft / geändert werden
- Reduziert den Netzwerkverkehr
- Erhöhte Sicherheit
Nachteile:
- SQL ist an die Datenbank gebunden (Vendor Lock-In).
- SQL-Code ist schwieriger zu pflegen
Externe Dateien (z. B. Eigenschaften- oder Ressourcendateien)
Vorteile
- SQL kann geändert werden, ohne dass die Anwendung neu erstellt werden muss
- Entkoppelt die SQL-Logik von der Geschäftslogik der Anwendung
- Zentrales Repository aller SQL-Anweisungen - einfacher zu warten
- Leichter zu verstehen
Nachteile:
- SQL-Code kann nicht mehr wartbar sein
- Es ist schwieriger, den SQL-Code auf (Syntax-) Fehler zu überprüfen
Eingebettet in SQLJ-Klauseln
Vorteile:
- Bessere Syntaxprüfung
Nachteile:
- Bindet zu eng an Java
- Geringere Leistung als JDBC
- Fehlende dynamische Abfragen
- Nicht so beliebt
Antworten:
Je größer die Anwendung in Bezug auf Größe und / oder Wiederverwendbarkeit ist, desto mehr müssen normalerweise die SQL-Anweisungen externalisiert / abstrahiert werden.
Hardcodiert (als statische Endkonstanten) ist der erste Schritt. Das Speichern in einer Datei (Eigenschaften / XML-Datei) ist der nächste Schritt. Metadatengesteuert (wie von einem ORM wie Hibernate / JPA ausgeführt) ist der letzte Schritt.
Hardcoded hat den Nachteil, dass Ihr Code wahrscheinlich DB-spezifisch wird und Sie bei jeder Änderung neu schreiben / neu erstellen / neu verteilen müssen. Vorteil ist, dass Sie es an 1 Stelle haben.
Das Speichern in einer Datei hat den Nachteil, dass sie beim Wachsen der Anwendung nicht mehr gewartet werden kann. Vorteil ist, dass Sie die App nicht neu schreiben / erstellen müssen, es sei denn, Sie müssen eine zusätzliche DAO-Methode hinzufügen.
Metadatengesteuert hat den Nachteil, dass Ihr Modellcode sehr eng mit dem Datenbankmodell gekoppelt ist. Für jede Änderung im Datenbankmodell müssen Sie den Code neu schreiben / neu erstellen / neu verteilen. Der Vorteil ist, dass es sehr abstrakt ist und dass Sie problemlos vom DB-Server wechseln können, ohne Ihr Modell ändern zu müssen (aber fragen Sie sich jetzt: Wie oft würde ein Unternehmen vom DB-Server wechseln? Wahrscheinlich nur einmal pro 3 Jahre, nicht wahr?) t es?).
Ich werde gespeicherte Prozeduren dafür nicht als "gute" Lösung bezeichnen. Sie haben einen ganz anderen Zweck. Auch wenn Ihr Code von der verwendeten Datenbank / Konfiguration abhängt.
quelle
Ich weiß nicht, ob dies optimal ist, aber meiner Erfahrung nach werden sie in der DAO-Ebene fest codiert (dh String-Literale).
quelle
Ich glaube nicht, dass Ihnen jemand die gewünschte Pro / Contra-Aufschlüsselung geben wird, da dies eine ziemlich große Frage ist. Stattdessen ist hier, was ich in der Vergangenheit verwendet habe und was ich in Zukunft verwenden werde.
Ich verwende SQL, das im DAL fest codiert ist. Ich fand das in Ordnung, bis die Datenbankadministratoren mit SQL spielen wollten. Dann müssen Sie es ausgraben, formatieren und an die Datenbankadministratoren weiterleiten. Wer wird darüber lachen und alles ersetzen. Aber ohne die schönen Fragezeichen oder die Fragezeichen in der falschen Reihenfolge und lassen Sie es zurück in den Java-Code.
Wir haben auch ein ORM verwendet, und obwohl dies für Entwickler großartig ist, haben unsere Datenbankadministratoren es gehasst, da es kein SQL gibt, über das sie lachen können. Wir haben auch ein ungerades ORM verwendet (ein benutzerdefiniertes ORM von einem Drittanbieter), das die Gewohnheit hatte, die Datenbank zu töten. Ich habe JPA seitdem verwendet und war großartig, aber es ist ein harter Kampf, etwas Kompliziertes hinter den DBAs zu bekommen.
Wir verwenden jetzt gespeicherte Prozeduren (wobei die Aufrufanweisung fest codiert ist). Das erste, worüber sich jeder beschweren wird, ist, dass Sie an die Datenbank gebunden sind. Du bist. Wie oft haben Sie jedoch die Datenbank geändert? Ich weiß, dass wir es einfach nicht einmal versuchen konnten, die Menge an anderem Code, die davon abhängt, sowie die Umschulung unserer Datenbankadministratoren und die Migration der Daten. Es wäre eine sehr teure Operation. Wenn jedoch in Ihrer Welt das Ändern von DBs im Handumdrehen erforderlich ist, sind SPs wahrscheinlich nicht verfügbar.
In Zukunft möchte ich gespeicherte Prozeduren mit Tools zur Codegenerierung verwenden, um Java-Klassen aus Oracle-Paketen zu erstellen.
Edit 2013-01-31 : Ein paar Jahre und DBAs später und wir verwenden jetzt Hibernate und gehen nur dann zu SQL (gespeicherte Prozesse in der DB), wenn dies unbedingt erforderlich ist. Dies ist meiner Meinung nach die beste Lösung. In 99% der Fälle müssen sich die DBs keine Gedanken über SQL machen, und die 1%, die sie tun, befinden sich an einem Ort, mit dem sie bereits vertraut sind.
quelle
Wenn Sie ein ORM (z. B. den Ruhezustand) verwenden, müssen Sie sich hoffentlich keine Sorgen um SQL-Anweisungen machen. Die Leistung ist normalerweise akzeptabel und Sie erhalten auch Herstellerunabhängigkeit.
quelle
Code.
Gespeicherte Prozeduren ermöglichen die Wiederverwendung, auch innerhalb anderer gespeicherter Prozeduren. Dies bedeutet, dass Sie eine Reise in die Datenbank unternehmen und unterstützende Anweisungen ausführen lassen können - das geringste Verkehrsaufkommen ist ideal. ORM oder sproc, die Zeit auf dem Draht zur Datenbank und zurück ist etwas, das Sie nicht wieder gutmachen können.
ORM eignet sich aufgrund seiner Abstraktion nicht zur Optimierung. IME, ORM bedeutet auch einen Mangel an referenzieller Integrität - erschweren die Berichterstattung über eine Datenbank. Was an Komplexität gespart wurde, hat jetzt zugenommen, um die Daten auf funktionsfähige Weise herausholen zu können.
Nein, Einfachheit ist. Die Lieferantenbindung erfolgt auch mit der Datenbank - SQL ist relativ standardisiert, es gibt jedoch immer noch herstellerspezifische Methoden.
quelle
Interessant ist die Angst vor einer Lieferantenbindung in der Java-Welt.
Ich hoffe, Sie haben nicht 50000 US-Dollar pro CPU für Oracle Enterprise bezahlt und dann nur den kleinsten gemeinsamen Nenner verwendet, um jede Minute zu MySQL zu wechseln. Wie jeder gute DBA Ihnen sagen wird, gibt es subtile Unterschiede zwischen den verschiedenen namhaften Datenbanken, insbesondere in Bezug auf Sperrmodelle und wie sie Konsistenz erreichen.
Treffen Sie also keine Entscheidung darüber, wie Sie Ihre SQL-Aufrufe nur nach dem Prinzip des herstellerunabhängigen SQL implementieren - haben Sie einen echten (geschäftlichen) Grund dafür.
quelle
SQL in gespeicherten Prozeduren wird vom Datenbanksystem optimiert und auf Geschwindigkeit kompiliert - das ist seine natürliche Heimat. SQL wird vom Datenbanksystem verstanden und vom Datenbanksystem analysiert. Behalten Sie Ihre SQL in der Datenbank, wenn Sie können; Wickeln Sie es in gespeicherte Prozeduren oder Funktionen oder in die vom Datenbanksystem bereitgestellten Logikeinheiten ein und rufen Sie es einfach mit einem der von Ihnen oder anderen genannten Tools auf.
Warum SQL-Code für das Datenbanksystem außerhalb der Datenbank speichern? Oft aus Gründen der Entwicklungsgeschwindigkeit. Warum ORM-Mapping verwenden? - Einige sagen, dass die ORM-Zuordnung Kompatibilität zwischen verschiedenen Datenbanksystemen bietet. In der realen Welt verlagert sich eine Anwendung jedoch selten von der Datenbankplattform, auf der sie erstellt wurde, insbesondere wenn erweiterte Funktionen wie die Replikation verwendet werden. In den seltenen Fällen, in denen das Datenbanksystem ausgetauscht wird, sind einige Arbeiten erforderlich . Ich glaube, einer der Nachteile von ORM ersetzt häufig mangelnde SQL-Kenntnisse oder mangelnde Sorgfalt beim Codieren in der Datenbank. Außerdem wird ORM niemals mit der Leistung nativer Datenbanken übereinstimmen, selbst wenn es nahe kommt.
Ich stehe auf der Seite, SQL-Code in der Datenbank zu behalten und ihn über eine beliebige API oder Schnittstelle, die Sie verwenden möchten, einfach aufzurufen. Abstraktieren Sie auch den Punkt, an dem Ihre Datenbankaufrufe getätigt werden, indem Sie diese Aufrufe hinter eine abstrakte Klasse oder OO-Schnittstelle stellen (ausgedrückt durch Methoden). Wenn Sie also jemals eine neue Art von Datenquelle austauschen, ist diese nahtlos mit der Geschäftsschicht verbunden .
quelle
Die einzige Frage, die Sie stellen und die eine eindeutige Antwort hat, lautet "Ist SQL-Code oder Metadaten?". Es ist definitiv Code und sollte daher in einer Art Quellcode-Kontrolle aufbewahrt werden und über ein System verfügen, mit dem Sie problemlos auf die neueste Version aktualisieren und wann zurücksetzen können nichts schief geht.
Ich habe drei Möglichkeiten gesehen, SQL in einer Anwendung auszuführen, und jede hat ihre Vor- und Nachteile. Es gibt keinen besten Weg, aber das Beste ist, einfach einen auszuwählen, der gut zu Ihrer Anwendung passt, und dabei zu bleiben.
quelle
Wir verwenden zufällig den iBatis SQL-Mapper, der näher am Metall liegt als ORMs wie Hibernate. In iBatis fügen Sie die SQL-Anweisungen in Ressourcendateien (XML) ein, die sich im Klassenpfad befinden müssen.
Ihre Liste der Ansätze scheint ziemlich umfassend zu sein, wenn Sie die ORM-Option von @ ocdecio hinzufügen. Ich würde sagen, dass die Verwendung eines ORM und eines SQL-Mappers und von Ressourcendateien die beiden besten Ansätze sind. Ich würde mich von SQLJ fernhalten, das nicht viel Akzeptanz gefunden hat und Sie zu eng mit Java verbindet. Halten Sie sich auch von gespeicherten Prozeduren fern, da diese Sie an einen bestimmten Datenbankanbieter binden (Standards für gespeicherte Prozeduren sind fast nicht vorhanden).
quelle
Wie die meisten von uns habe ich die ganze Gammut gesehen, aber wir müssen SQL als eine erstklassige Sprache betrachten. Ich habe sogar SQL in der Datenbank gespeichert gesehen, das heruntergezogen und dann wieder ausgeführt wird.
Die erfolgreichsten Systeme, die ich gesehen habe, verwenden gespeicherte Prozeduren, Funktionen und Ansichten.
Gespeicherte Prozesse halten den SQL-Text in der Datenbank zurück und ermöglichen eine relativ sofortige Änderung durch die DEPLOYING- und CUSTOMIZING-Prozesse (für deren Unterstützung viel geeignetes Design erforderlich ist).
Alle Projektionen sollten aus den gleichen Gründen über Ansichten und einfache Auswahlen erfolgen. Die gesamte Projektionslogik sollte in der Ansicht enthalten sein.
quelle
Ich schlage vor, DAOs mit einem Factory-Layout zu verwenden. Die Beispielobjekte, die Sie benötigen, wären also:
Dieser Stil überlagert die Dateninteraktion, sodass Sie nur eine Codeebene ändern müssen, wenn Sie die Datenbank wechseln oder zu ORM-Technologien wechseln.
quelle
Es gibt keinen wesentlichen Unterschied zwischen diesen drei:
Ich gehe davon aus, dass Sie SQL-Code in einer Zeichenfolge direkt in Ihren Java-Code einbetten. Während 1 und 3 wahrscheinlich JDBC direkt verwenden werden (oder ein Tool wie Apache DbUtils ), fügt 2 dem Stapel eine Präprozessortechnologie hinzu, die den relevanten JDBC-Code vor der Kompilierung generiert.
Wenn diese Lösungen das Einbetten von SQL beinhalten, können Sie im Wesentlichen auch eine der folgenden Technologien verwenden:
Möglicherweise gibt es auch andere Tools, mit denen Sie SQL typsicherer in Java einbetten können als durch SQLJ oder durch tatsächliche Verkettung von Zeichenfolgen.
quelle
Aus meiner Erfahrung heraus ist die harte Codierung von SQL-Anweisungen in den DAO-Objekten weit verbreitet. Ich denke jedoch, dass dies die am wenigsten bevorzugte Methode sein sollte. Die beste Vorgehensweise sollte darin bestehen, die SQL-Anweisungen in einer Eigenschaftendatei zu speichern. Rufen Sie die Anweisungen im DAO-Objekt über eine Schnittstelle zu Eigenschaftendateien ab, z . B. java.util.Properties . Die SQL-Anweisungen können mit '?' Durchsetzt werden, um Parameter über eine vorbereitete Anweisung zu übergeben Ansatz für .
Ein solcher Ansatz hilft dabei, die SQL-Logik von der Geschäftslogik der Anwendung zu entkoppeln. Dadurch wird ein zentrales Repository für alle SQL-Anweisungen verfügbar, wodurch die Änderung vereinfacht wird und die Suche nach Datenbankanweisungen innerhalb der Anwendungslogik entfällt. Die Verständlichkeit wird ebenfalls verbessert.
quelle
Meine landen in Ressourcenbündeln. Ich weiß, dass es nicht normal ist, aber es ist für mich und jeden "außer mir" am einfachsten zu pflegen. Es ist einfach und logisch.
Ich bin eigentlich gespannt, ob jemand meinen Ansatz auch nutzt.
quelle
Als Rexem schrieb, sind SQL-Anweisungen Code - sie sollten wie Code behandelt werden, nicht externalisiert (außer Sie haben gute Gründe), sondern mit Code platziert werden, der SQL-Daten von / zu diesen Anweisungen verarbeitet. Die heutigen Framework-ORMs / iBatis bieten viele Vereinfachungen für die tägliche JDBC-Entwicklung.
Einige Antworten auf Ihre Frage finden Sie in dieser Frage :) Das Problem, wie Ihre SQL-Anweisungen gespeichert werden, hängt vom König Ihrer Anwendung ab. Was sind deine Bedürfnisse? Hohe Sicherheit, einfaches Schreiben von Code oder Wartung, plattformübergreifende oder Lieferantenbindung? Die nächste Frage, die Sie benötigen, ist ein reines SQL- oder ORM-Framework.
Einfachste Lösung (P), schwer zu warten (C)
Beter Syntaxprüfung (P), Mangel an dynamischen Abfragen (C), geringere Leistung als JDBC (C), nicht so beliebt (C)
Es muss ein konkreter Fall sein, dass Sie dies tun sollten (C) oder wenn Sie ORM (P) meinen;)
Leicht zu pflegen (P), aber schwerer auf Fehler zu überprüfen (C)
Hohe Sicherheit (P), Code, der schwer zu lösen ist, um Probleme mit der Lieferantenbindung zu lösen (C)
quelle