2012-09-01 6 views
5

Ich habe ein viel verwendetes Projekt, das ich gerade aktualisiere. Es gibt mehrere Stellen, an denen dieses Projekt installiert werden kann, und in der Zukunft ist es nicht sicher, welche Version wo verwendet wird und auf welche Version man in der Zukunft aktualisiert werden könnte. Im Moment sind sie alle gleich.HSQL erstellen Tabellenabfrage erstellen aus Klasse

Mein Problem rührt von der Tatsache her, dass es viele Änderungen an den Hibernate-Entity-Klassen geben kann, und es muss einfach und ohne Datenbankverlust auf eine neuere Version aktualisiert werden können. Einfach WAR ersetzen und starten und es sollte sich migrieren.

Hibernate macht keine Änderungen an Tabellen, es sei denn hibernate.hbm2ddl.auto = erstellen, aber die tatsächlich alle Daten wegwirft?

Jetzt, wenn der Spring-Kontext vollständig geladen ist, führt er eine Bean aus, die die Datenbank auf die aktuelle Version migriert, indem sie alle Änderungen von VersionX zu VersionY durchläuft (welche Version zuvor in der Datenbank gespeichert wurde) und ändern Sie die Tabelle manuell.

Es ist nicht viel Aufwand ein paar hartcodierte ALTER TABLE einige Spalten hinzufügen zu tun, aber wenn es um das Hinzufügen komplett neue Tabellen kommt, fühlt es dumm, alles zu schreiben zu haben ...

Also meine Frage (n) ist diese:

  • gibt es eine Möglichkeit, um eine Entity-Klasse und einen Dialekt zu schicken irgendwo Code Hibernate, und erhalten Sie eine gültige SQL-Abfrage zum Erstellen einer Tabelle zurück?

  • Und noch besser, irgendwie erstellen Sie eine SQL-Zeichenfolge zum Hinzufügen einer Spalte zu einer Tabelle, Dialekt-Safe?

Ich hoffe, dass dies nicht eine dumme Frage ist, und ich habe nicht etwas offensichtlich verpasst, wenn es um Hibernate kommt ...

Antwort

2

Ich glaube nicht, Sie in der Lage sein werden, um diese vollständig zu automatisieren. Hibernate verfügt über das Werkzeug hbm2ddl (verfügbar als Ant-Task oder Maven-Plugin), um die erforderlichen DDL-Anweisungen aus Ihrer Hibernate-Konfiguration zu erzeugen, um eine leere Datenbank zu erstellen. Ich kenne jedoch keine Tools, die ein automatisches "Diff" zwischen zwei vornehmen können Versionen. In jedem Fall ist es wahrscheinlich besser, wenn Sie das Diff sorgfältig von Hand machen, da nur Sie Ihr Objektmodell gut genug kennen, um die richtigen Standardwerte für neue Eigenschaften bestehender Entitäten usw. auswählen zu können.

Sobald Sie Ihre Diffs ausgearbeitet haben, können Sie ein Tool wie liquibase verwenden, um sie zu verwalten und die Updates zum Zeitpunkt des Starts der Anwendung auf eine Datenbank anzuwenden.

+1

Okay, ich entschied mich für das ist die bessere Antwort. Ich habe immer noch Vorbehalte, um mich selbst als Abhängigkeit abzuhängen oder meine Spring + Hibernate + Annotations anzupassen, aber es hat eine großartige Arbeit geleistet, hartcodierte SQL-Abfragen zu erstellen, die ich für meine eigene, benutzerdefinierte Lösung verwenden kann. Vielen Dank. – Stmated

+1

Überprüfen Sie diese Antwort von Dipesh: http://stackoverflow.com/a/12259980/433789 – sdouglass

+1

Lassen Sie Hibernate seine eigene automatische Aktualisierung funktioniert gut in einfachen Fällen wie das Hinzufügen neuer Nullable-Spalten, aber es wird nicht komplizierter bewältigen Migrationen wie das Umbenennen oder Entfernen von Spalten, Ändern von Typen usw. Stellen Sie sich eine Situation vor, in der Sie eine neue Spalte hinzufügen, deren Wert basierend auf Werten in vorhandenen Spalten berechnet werden muss (anstatt nur einen statischen Standardwert für alle vorhandenen Zeilen zu haben)). –

2

Vielleicht sollten Sie einen anderen Ansatz versuchen. Anstatt ein Schema bei der Laufzeitaktualisierung zu erzeugen, sollte man es "von Hand" machen (könnte jedoch auf einem Hibernate-generierten Skript basieren).

Speichern Sie eine Versionsnummer in der Datenbank und erstellen Sie ein Update-Skript für jede nächste Version. Das einzige, was Sie jetzt tun müssen, ist festzustellen, in welcher Version sich die Datenbank gerade befindet und nacheinander die notwendigen Update-Skripte auszuführen, um sie auf die aktuelle Version zu bringen.

Um es besonders robust zu machen, können Sie einen Einheiten-/Integrationstest durchführen, der alle möglichen Datenbankaktualisierungen ausführt und die Integrität der resultierenden Datenbank überprüft.

Ich habe diese Methode für eine Anwendung verwendet, ich baue und es funktioniert einwandfrei. Ein anderes Beispiel für eine Implementierung dieses Musters ist Android. Sie haben eine Upgrade-Methode in ihrer API

http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)

+1

Ich glaube, ich dies als akzeptierte Antwort nehmen. Bedauerlicherweise fühle ich mich seltsam, wenn ich das Kopfgeld gebe, weil es nicht wirklich eine Antwort auf meine Frage ist; und ist die Lösung, auf die ich mich einlassen würde, wenn meine Frage tatsächlich für unmöglich gehalten würde. Aber ich denke, es war der, der am ehesten meinen eigenen Vorstellungen entsprach, keine zusätzlichen Abhängigkeiten und ähnliches einzubringen. Danke – Stmated

+1

Ernsthaft, sollten Sie sich Liquibase und insbesondere seine [Ruhezustand-Unterstützung] (http://liquibase.org/manual/hibernate) gut ansehen ... –

+1

tat ich; obwohl ich einige Bedenken dagegen hatte, als ich die Dokumentation las. Mag sein, dass ich nicht gründlich genug gelesen habe und nicht herausgefunden habe, wie ich es gut mit meiner Umgebung kombinieren kann. Könnte mit einer revidierten Akzeptanz zurückkommen, wenn sich die Dinge ändern. – Stmated

4

haben Sie

versucht
hibernate.hbm2ddl.auto=update 

es mit den Daten alle die Datenbank behält und nur die Spalten und Tabellen, die Sie haben in der Entität geändert hängen.

+1

Das ist, was ich benutze, es funktioniert super. – sdouglass

2

Verwenden Sie nicht Hibernate's ddl. Es wirft Ihre Daten weg, wenn Sie migrieren möchten. Ich schlage vor, Sie schauen sich Liquibase an. Liquibase ist eine Datenbankversionssteuerung. Es funktioniert mit Changesets. Jeder Changeset kann manuell erstellt werden oder Sie können Liquibase Ihre Hibernate-Konfiguration lesen lassen und einen Changeset generieren lassen.

Liquibase über Frühling gestartet werden kann, so dass es direkt mit Ihrem Projekt passen sollte ;-)