Ruhezustand oder JDBC

68

Ich habe eine Java-Swing-Anwendung mit einem Thick-Client mit einem Schema von 25 Tabellen und ~ 15 JInternalFrames (Dateneingabeformulare für die Tabellen). Ich muss für die DBMS-Interaktion eine Entwurfsauswahl für gerades JDBC oder ORM (in diesem Fall Ruhezustand mit Federrahmen) treffen. Das Erstellen aus der Anwendung wird in Zukunft erfolgen.

Wäre der Winterschlaf für ein Projekt dieser Größe übertrieben? Eine Erklärung der Antwort mit Ja oder Nein wäre sehr willkommen (oder sogar ein anderer Ansatz, wenn dies gerechtfertigt ist).

TIA.

jmq
quelle
There are other possibilities. What about iBATIS iBATIS.apache.org
Adrian Pronk
overkill? Conceptual overkill ? Another jar ?
Surya
2
I was thinking overkill in extra processing overhead to add a layer, extra developer skills needed to maintain it (I have the skills, but I have to think about when I'm not the one maintaining it), coupling to a 3rd party instead of native (though the extra jars are not an issue AFAIC). That type of thing.
jmq
6
+1 für gute Fragestellung und klare Frage
KLE

Antworten:

186

Gute Frage ohne einfache Antwort.

Ich war ein großer Fan von Hibernate, nachdem ich es über mehrere Jahre in mehreren Projekten verwendet hatte. Früher war ich der Meinung, dass jedes Projekt standardmäßig in den Ruhezustand versetzt werden sollte.

Heute bin ich mir nicht so sicher.

Hibernate (und JPA) eignen sich hervorragend für einige Dinge, insbesondere zu Beginn des Entwicklungszyklus. Es ist viel schneller, mit Hibernate zu arbeiten, als mit JDBC. Sie erhalten viele Funktionen zum kostenlosen Caching, zum optimistischen Sperren und so weiter.

Auf der anderen Seite hat es einige versteckte Kosten. Der Ruhezustand ist zu Beginn täuschend einfach . Befolgen Sie ein Tutorial, fügen Sie Ihrer Klasse einige Anmerkungen hinzu - und Sie haben Ausdauer. Aber es ist nicht einfach und um guten Code darin schreiben zu können, muss man sowohl die internen Abläufe als auch das Datenbankdesign gut verstehen. Wenn Sie gerade erst anfangen, sind Ihnen möglicherweise einige Probleme nicht bekannt, die Sie später beißen könnten. Hier ist eine unvollständige Liste.

Performance

Die Laufzeitleistung ist gut genug, ich habe noch keine Situation gesehen, in der der Ruhezustand der Grund für die schlechte Leistung in der Produktion war . Das Problem ist die Startleistung und wie sie sich auf die Zeit und die Entwicklungsleistung Ihrer Unit-Tests auswirkt. Wenn der Ruhezustand geladen wird, werden alle Entitäten analysiert und viele Vor-Caching-Vorgänge ausgeführt. Bei einer nicht sehr großen Anwendung kann dies etwa 5-10-15 Sekunden dauern. Ihr 1-Sekunden-Unit-Test dauert also jetzt 11 Sekunden. Kein Spaß.

Datenbankunabhängigkeit

Es ist sehr cool, solange Sie keine Feinabstimmung an der Datenbank vornehmen müssen.

In-Memory-Sitzung

Für jede Transaktion speichert Hibernate ein Objekt im Speicher für jede Datenbankzeile, die es "berührt". Es ist eine schöne Optimierung, wenn Sie eine einfache Dateneingabe vornehmen. Wenn Sie jedoch aus irgendeinem Grund viele Objekte verarbeiten müssen, kann dies die Leistung erheblich beeinträchtigen, es sei denn, Sie bereinigen die In-Memory-Sitzung explizit und sorgfältig selbst.

Kaskaden

Mit Kaskaden können Sie die Arbeit mit Objektdiagrammen vereinfachen. Wenn Sie beispielsweise ein Stammobjekt und einige untergeordnete Objekte haben und das Stammobjekt speichern, können Sie den Ruhezustand so konfigurieren, dass auch untergeordnete Objekte gespeichert werden. Das Problem beginnt, wenn Ihr Objektdiagramm komplexer wird. Wenn Sie nicht äußerst vorsichtig sind und ein gutes Verständnis dafür haben, was intern vor sich geht, ist es leicht, dies durcheinander zu bringen. Und wenn Sie dies tun, ist es sehr schwierig, diese Probleme zu beheben.

Faules Laden

Lazy Loading bedeutet, dass der Ruhezustand jedes Mal, wenn Sie ein Objekt laden, nicht alle zugehörigen Objekte lädt, sondern Platzhalter bereitstellt, die aufgelöst werden, sobald Sie versuchen, auf sie zuzugreifen. Tolle Optimierung, oder? Es ist so, außer dass Sie sich dieses Verhaltens bewusst sein müssen, sonst erhalten Sie kryptische Fehler. Google "LazyInitializationException" für ein Beispiel. Und seien Sie vorsichtig mit der Leistung. Abhängig von der Reihenfolge, in der Sie Ihre Objekte und Ihr Objektdiagramm laden, können Sie auf "n + 1 wählt Problem aus" klicken. Google es für weitere Informationen.

Schema-Upgrades

Der Ruhezustand ermöglicht einfache Schemaänderungen, indem nur Java-Code umgestaltet und neu gestartet wird. Es ist großartig, wenn Sie anfangen. Aber dann veröffentlichen Sie Version eins. Und wenn Sie Ihre Kunden nicht verlieren möchten, müssen Sie ihnen Schema-Upgrade-Skripte bereitstellen. Dies bedeutet kein einfacheres Refactoring mehr, da alle Schemaänderungen in SQL durchgeführt werden müssen.

Ansichten und gespeicherte Prozeduren

Für den Ruhezustand ist exklusiver Schreibzugriff auf die Daten erforderlich, mit denen er arbeitet. Dies bedeutet, dass Sie Ansichten, gespeicherte Prozeduren und Trigger nicht wirklich verwenden können, da diese Änderungen an Daten verursachen können, deren Ruhezustand sie nicht kennt. Einige externe Prozesse können Daten in separaten Transaktionen in die Datenbank schreiben. In diesem Fall enthält Ihr Cache jedoch ungültige Daten. Welches ist eine weitere Sache, um die man sich kümmern muss.

Single Threaded Sessions

Sitzungen im Ruhezustand sind Single-Threaded-Sitzungen. Auf jedes Objekt, das über eine Sitzung geladen wurde, kann nur von demselben Thread aus zugegriffen werden (einschließlich Lesen). Dies ist für serverseitige Anwendungen akzeptabel, kann jedoch unnötige Probleme verursachen, wenn Sie eine GUI-basierte Anwendung ausführen.

Ich denke mein Punkt ist, dass es keine kostenlosen Mahlzeiten gibt.

Der Ruhezustand ist ein gutes Werkzeug, aber es ist ein komplexes Werkzeug, und es erfordert Zeit, um es richtig zu verstehen. Wenn Sie oder Ihre Teammitglieder nicht über solche Kenntnisse verfügen, ist es möglicherweise einfacher und schneller, für eine einzelne Anwendung reines JDBC (oder Spring JDBC) zu verwenden. Wenn Sie jedoch bereit sind, Zeit in das Lernen zu investieren (einschließlich Learning by Doing und Debugging), können Sie die Kompromisse in Zukunft besser verstehen.

Gregory Mostizky
quelle
5
+1 Tolle Antwort. Früher dachte ich, der Ruhezustand sei das Beste, aber als unsere Anwendung immer komplexer wurde (größere Objektdiagramme), bin ich auf einige Szenarien gestoßen, in denen das Debuggen ein Albtraum war, weil ich keine Ahnung hatte, was der Ruhezustand ist tun. (Zum Glück ist es Open Source, also konnte ich die Quelle durchsuchen, um es herauszufinden. NICHT SPASS) Wie auch immer, ich stimme zu. Keine kostenlosen Mahlzeiten. Der Ruhezustand ist großartig, aber es gibt Kompromisse.
Delux247
1
Ist das noch aktuell, seit es der erste Hit bei Google ist?
PowerFlower
@PowerFlower Für 2018 denke ich, dass es immer noch eine sehr ähnliche Situation ist. Das Kernmerkmal des Ruhezustands hat sich nicht geändert und wird es wahrscheinlich auch nie.
Trump 2020 - Gerechtigkeit wird kommen
20

Der Ruhezustand kann gut sein, aber er und andere JPA-ORMs bestimmen in der Regel Ihre Datenbankstruktur bis zu einem gewissen Grad. Zusammengesetzte Primärschlüssel können beispielsweise in Hibernate / JPA erstellt werden, sind jedoch etwas umständlich. Es gibt andere Beispiele.

Wenn Sie mit SQL vertraut sind, empfehle ich Ihnen dringend, sich Ibatis anzusehen . Es kann über 90% dessen leisten, was Hibernate kann, ist jedoch in der Implementierung weitaus einfacher.

Ich kann mir keinen einzigen Grund vorstellen, warum ich jemals JDBC (oder sogar Spring JDBC) anstelle von Ibatis gewählt habe. Der Ruhezustand ist eine komplexere Wahl.

Schauen Sie sich das Spring and Ibatis Tutorial an .

Cletus
quelle
12

Zweifellos hat der Ruhezustand seine Komplexität.

Aber was ich am Hibernate-Ansatz (einige andere auch) wirklich mag, ist das konzeptionelle Modell, das Sie in Java erhalten können, ist besser. Obwohl ich OO nicht als Allheilmittel betrachte und nicht nach theoretischer Reinheit des Designs suche, habe ich so oft festgestellt, dass OO meinen Code tatsächlich vereinfacht. Da Sie speziell nach Details gefragt haben, sind hier einige Beispiele:

  • Die zusätzliche Komplexität ist nicht im Modell enthalten und Entitäten, sondern in Ihrem Framework, um beispielsweise alle Entitäten zu manipulieren. Für Betreuer besteht der schwierige Teil nicht aus wenigen Framework-Klassen, sondern aus Ihrem Modell. Mit Hibernate können Sie den schwierigen Teil (das Modell) auf dem saubersten Stand halten.

  • Wenn in all Ihren Entitäten ein Feld (wie eine ID oder Überwachungsfelder usw.) verwendet wird, können Sie damit eine Oberklasse erstellen . Deshalb :

    • Sie schreiben weniger Code, aber was noch wichtiger ist ...
    • Ihr Modell enthält weniger Konzepte (das eindeutige Konzept ist im Code eindeutig).
    • Sie können kostenlos allgemeineren Code schreiben, der mit einer Entität (unbekannt, keine Typumschaltung oder Umwandlung) versehen ist und Ihnen den Zugriff auf die ID ermöglicht.
  • Der Ruhezustand bietet auch viele Funktionen, um mit anderen Modellmerkmalen umzugehen, die Sie möglicherweise benötigen (jetzt oder später fügen Sie sie nur nach Bedarf hinzu). Nehmen Sie es als Erweiterungsqualität für Ihr Design.

    • Sie können die Vererbung (Unterklasse) durch die Zusammensetzung ersetzen (mehrere Entitäten mit demselben Mitglied, das einige verwandte Felder enthält, die zufällig in mehreren Entitäten benötigt werden).
    • Es kann eine Vererbung zwischen einigen Ihrer Entitäten geben. Es kommt häufig vor, dass Sie zwei Tabellen mit nahezu derselben Struktur haben (Sie möchten jedoch nicht alle Daten in einer Tabelle speichern, da Sie die referenzielle Integrität für eine andere übergeordnete Tabelle verlieren würden).
  • Bei der Wiederverwendung zwischen Ihren Entitäten (jedoch nur bei angemessener Vererbung und Zusammensetzung ) ergeben sich normalerweise einige zusätzliche Vorteile. Beispiele:

    • Es gibt oft eine Möglichkeit, die Daten der Entitäten zu lesen, die ähnlich, aber unterschiedlich sind. Angenommen, ich lese das Feld "Titel" für drei Entitäten, aber für einige ersetze ich das Ergebnis durch einen anderen Standardwert, wenn es null ist. Es ist einfach, eine Signatur "getActualTitle" (in einer Oberklasse oder einer Schnittstelle) zu haben und die Standardwertbehandlung in den drei Implementierungen zu implementieren. Das heißt, der Code aus meinen Entitäten befasst sich nur mit dem Konzept eines "tatsächlichen Titels" (ich habe dieses Funktionskonzept explizit gemacht), und die Methodenvererbung sorgt dafür, dass der richtige Code ausgeführt wird (kein Schalter mehr oder wenn, keine Codeduplizierung). .
    • ...
  • Im Laufe der Zeit entwickeln sich die Anforderungen. Es wird einen Punkt geben, an dem Ihre Datenbankstruktur Probleme hat. Nur mit JDBC muss sich jede Änderung an der Datenbank auf den Code auswirken (dh doppelte Kosten). In Hibernate können viele Änderungen übernommen werden, indem nur die Zuordnung und nicht der Code geändert wird. Das Gleiche passiert umgekehrt: Im Ruhezustand können Sie Ihren Code (z. B. zwischen Versionen) ändern, ohne Ihre Datenbank zu ändern (die Zuordnung zu ändern, obwohl dies nicht immer ausreicht). Zusammenfassend lässt sich sagen, dass Sie mit Hibernate Ihre Datenbank und Ihren Code unabhängig voneinander weiterentwickeln können .

Aus all diesen Gründen würde ich Hibernate wählen :-)

KLE
quelle
5

Ich denke, beides ist eine gute Wahl, aber ich persönlich würde den Ruhezustand verwenden. Ich denke nicht, dass der Ruhezustand für ein Projekt dieser Größe übertrieben ist.

Wo Hibernate für mich wirklich glänzt, ist der Umgang mit Beziehungen zwischen Entitäten / Tabellen. Das manuelle Ausführen von JDBC kann viel Code erfordern, wenn Sie Eltern und Kinder (Enkelkinder, Geschwister usw.) gleichzeitig ändern. Der Ruhezustand kann dies zu einem Kinderspiel machen (häufig reicht ein einziges Speichern der übergeordneten Entität aus).

Es gibt jedoch sicherlich Komplexitäten beim Umgang mit dem Ruhezustand, z. B. das Verständnis der Funktionsweise des Sitzungsspülens und das langsame Laden.

Brian Yarger
quelle
3

Straight JDBC würde bestenfalls in die einfachsten Fälle passen.

Wenn Sie in Java und OOD bleiben möchten, sollten Sie sich für Hibernate oder Hibernate / JPA oder einen anderen JPA-Anbieter / JPA entscheiden.

Wenn Sie mit SQL besser vertraut sind, schadet es nicht, Spring for JDBC-Vorlagen und andere SQL-orientierte Frameworks zu haben.

Im Gegensatz dazu hilft Spring neben der Transaktionskontrolle nicht viel, wenn Sie mit JPA arbeiten.

Spitzenkoch
quelle
3

Der Ruhezustand eignet sich am besten für Middleware-Anwendungen. Angenommen, wir bauen eine Middleware auf der Datenbank auf. Auf die Mittelware wird von etwa 20 Anwendungen zugegriffen. In diesem Fall können wir einen Ruhezustand haben, der die Anforderungen aller 20 Anwendungen erfüllt.

Asok B.
quelle
Wissen Sie beim Testen oder Debuggen, welche Kopfschmerzen es sein wird?
Wiedergeboren am
1
  1. Wenn wir in JDBC eine Datenbankverbindung öffnen, müssen wir in try schreiben, und wenn Ausnahmen aufgetreten sind, wird catch block dies tun und schließlich zum Schließen der Verbindungen verwendet.

  2. In jdbc sind alle Ausnahmen geprüfte Ausnahmen, daher müssen wir Code in try, catch und throw schreiben, aber im Ruhezustand haben wir nur nicht geprüfte Ausnahmen

  3. Hier müssen wir als Programmierer die Verbindung schließen, sonst haben wir möglicherweise die Möglichkeit, unsere Verbindungsnachricht zu erhalten…!

  4. Wenn wir die Verbindung im finally-Block nicht geschlossen haben, ist jdbc nicht dafür verantwortlich, diese Verbindung zu schließen.

  5. In JDBC müssen wir SQL-Befehle an verschiedenen Stellen schreiben. Nachdem das Programm erstellt wurde, wenn die Tabellenstruktur geändert wurde, funktioniert das JDBC-Programm nicht. Auch hier müssen wir die erforderlichen Änderungen ändern, kompilieren und erneut bereitstellen, was mühsam ist.

  6. JDBC wird verwendet, um datenbankbezogene Fehlercodes zu generieren, wenn eine Ausnahme auftritt. Java-Programmierer kennen diese Fehlercodes jedoch nicht.

  7. Wenn wir beim Einfügen eines Datensatzes keine bestimmte Tabelle in der Datenbank haben, löst JDBC einen Fehler wie "Ansicht nicht vorhanden" aus und löst eine Ausnahme aus. Im Ruhezustand wird jedoch keine Tabelle in der Datenbank gefunden Datenbank erstellt dies die Tabelle für uns

  8. JDBC unterstützt das Laden von LAZY und Hibernate unterstützt das Laden von Eager

  9. Der Ruhezustand unterstützt Vererbung, Zuordnungen, Sammlungen

  10. Wenn wir im Ruhezustand das abgeleitete Klassenobjekt speichern, wird auch sein Basisklassenobjekt in der Datenbank gespeichert. Dies bedeutet, dass der Ruhezustand die Vererbung unterstützt

  11. Der Ruhezustand unterstützt Beziehungen wie Eins-zu-viele, Eins-zu-eins, viele-zu-viele-zu-viele, viele-zu-eins

  12. Der Ruhezustand unterstützt den Caching-Mechanismus, wodurch die Anzahl der Roundtrips zwischen einer Anwendung und der Datenbank verringert wird. Durch Verwendung dieser Caching-Technik wird die Anwendungsleistung automatisch erhöht

  13. Paginierung im Winterschlaf zu bekommen ist ganz einfach.

  14. Im Ruhezustand können Primärschlüssel automatisch generiert werden, während die Datensätze in einer Datenbank gespeichert werden

Creditto
quelle
mit der Veröffentlichung von Java 1.7 und seiner Funktion Try-with-Resources. Argumente 1,3 und 4 sind kein Problem mehr
Reborn
0

... In-Memory-Sitzung ... LazyInitializationException ...

Sie könnten sich Ebean ORM ansehen, das keine Sitzungsobjekte verwendet ... und bei dem das verzögerte Laden einfach funktioniert. Sicherlich eine Option, kein Overkill, und wird einfacher zu verstehen sein.

Rob Bygrave
quelle
0

Wenn Milliarden von Benutzern die App oder das Web verwenden, wird die Abfrage in jdbc milliardenfach ausgeführt, aber im Ruhezustand wird die Abfrage nur einmal für eine beliebige Anzahl von Benutzern ausgeführt, der wichtigste und einfachste Vorteil des Ruhezustands gegenüber jdbc.

Ankesh Roy
quelle