Wie importiere ich Anfangsdaten mit Hibernate in die Datenbank?

68

Bei der Bereitstellung von Anwendungen verwende ich häufig die Kapazität von Hibernate, um ein Datenbankschema zu erstellen, um die Bereitstellung zu vereinfachen. Dies kann leicht durch Konfigurieren der Eigenschaft hibernate.hbm2ddl.auto erreicht werden.

Gelegentlich muss ich jedoch auch einige Anfangsdaten in die Datenbank einfügen, z. B. Root-Benutzer. Gibt es eine Möglichkeit, dies über den Ruhezustand mit einer Art Textdatei zu erreichen?

Ich weiß, dass ich den Code, der dies tun wird, leicht programmieren kann, aber ich frage mich nur, ob es bereits ein Dienstprogramm gibt, das mir helfen kann, dasselbe über die Konfiguration zu erreichen.

Dan
quelle

Antworten:

84

Ich habe dies durch eine Suche nach "Hibernate Fixtures" gefunden:

Hibernate erstellt die Datenbank, wenn die Entity Manager-Factory erstellt wird (tatsächlich, wenn die SessionFactory von Hibernate von der Entity Manager-Factory erstellt wird). Wenn eine Datei mit dem Namen import.sql im Stammverzeichnis des Klassenpfads ('/import.sql') vorhanden ist, führt Hibernate die aus der Datei gelesenen SQL-Anweisungen nach der Erstellung des Datenbankschemas aus. Beachten Sie, dass Hibernate das Schema vor dem Erstellen leert (alle Tabellen, Einschränkungen oder sonstigen Datenbankobjekte löscht, die beim Erstellen des Schemas erstellt werden sollen).

Quelle: http://www.velocityreviews.com/forums/t667849-hibernate-quotfixturesquot-or-database-population.html

Probieren Sie es aus und lassen Sie uns wissen, ob es funktioniert!

Matt Sidesinger
quelle
5
Soweit ich sehen kann, scheint die SQL nicht db-agnostisch zu sein
Dan
+! für die import.sql sollte in der Wurzel nicht nur irgendwo sein
Eyad Ebrahim
63

Das Hinzufügen von import.sql zum Klassenpfad funktioniert hervorragend. Hbm2ddl prüft, ob die Datei vorhanden ist, und führt sie aus. Das einzige zusätzliche Detail ist, dass sich jeder SQL-Befehl in einer eigenen Zeile befinden muss, da er sonst nicht ausgeführt werden kann.

Dies wird auch nur funktionieren , wenn hbm2ddl.autofestgelegt ist createoder create-drop.

Mauro De Lucca
quelle
21
Es funktioniert auch nur, wenn hbm2ddl.auto auf "create" oder "create-drop" eingestellt ist.
Amorfis
1
Dieser Kommentar war wirklich hilfreich von mir.
Marcin Cylke
2
Die Anforderung, jede SQL-Anweisung in eine separate Zeile zu setzen, ist seltsam. Vielen Dank für den Hinweis
Tahir Akhtar
1
Sie können mehrzeilige SQL-Befehle aktivieren, indem Sie sie <property name="hibernate.hbm2ddl.import_files_sql_extractor">org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor</property>zu Ihrem hibernate.cfg.xml( stackoverflow.com/a/15090964 )
cooljeffro
45

Fügen Sie in Ihrer Ruhezustandskonfiguration die Eigenschaft hibernate.hbm2ddl.import_files hinzu . Ändern Sie die zu erstellende Eigenschaft hibernate.hbm2ddl.auto. Fügen Sie initial_data.sql im Verzeichnis / classes mit dem anfänglichen SQL-Code hinzu, um Daten einzufügen. Führen Sie den Ruhezustand aus, nachdem Sie das Datenbankschema erstellt haben.

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <prop key="hibernate.hbm2ddl.import_files">initial_data.sql</prop>
        </props>
    </property>
</bean>

Wenn Sie in Ihrer Konfiguration für den Ruhezustand keine Eigenschaft hinzufügen möchten, können Sie eine Datei import.sql im Verzeichnis / classes erstellen. Im Ruhezustand wird diese standardmäßig verwendet, wenn die Eigenschaft hibernate.hbm2ddl.auto gleich create ist

punseti
quelle
22

Warum hbm2ddl.autound hbm2ddl.import_filesEigenschaften sind böse

(Bei Missbrauch als Tool für das Datenbankänderungsmanagement)

Wie bereits an anderer Stelle erwähnt, weist die Verwendung hibernate.hbm2ddl.autound hibernate.hbm2ddl.import_filesVerwaltung von Datenbankänderungen einige schwerwiegende Nachteile auf:

  1. Nur die Struktur kann geändert werden. Bestehende Werte können überschrieben oder im schlimmsten Fall einfach an Nirvana gesendet werden. Ohne ein Werkzeug wie liquibase oder scriptella , Sie haben keine ETL - Funktionen.
  2. Diese Methode hat keine Transaktionen. Sowohl die Struktur als auch die Datenanweisungen werden ausgeführt, bevor ein Transaktionsmanager übernimmt. Angenommen, Sie haben einen Fehler in Anweisung 42 von 256. Ihre Datenbank befindet sich jetzt in einem inkonsistenten Zustand.
  3. Imvho, Sie verlieren Transparenz und Kontrolle: Wenn ein Scriptella-Skript oder eine Liquibase-Änderung zusammen mit den Änderungen in den Domänenmodellen festgelegt oder normalerweise festgeschrieben wird, ändern Sie das Domänenmodell und hoffen (im Grunde), dass der Ruhezustand herausfindet, was zu tun ist. (Das tut es nicht, aber das ist eine andere Geschichte.)
  4. Für den Integrations-, System- und Abnahmetest gehen Sie lediglich davon aus, dass sich Ihre Testdatenbanken im absolut exakt gleichen Zustand wie Ihre Produktionsdatenbank befinden. Das muss man manuell nachverfolgen (Viel Glück und viel Spaß damit !;)). Wenn Sie einen Fehler machen, ist nur ein kleiner Ausrutscher ausreichend. Die Ergebnisse können sehr katastrophal sein.

Ich persönlich verwende liquibase für das Datenbankänderungsmanagement und habe den folgenden Workflow entwickelt, um die Wartungsarbeiten zu reduzieren:

  • Erstellen Sie ein Änderungsprotokoll über die Befehlszeile meiner letzten Release-Struktur
  • Erstellen Sie ein Änderungsprotokoll meiner neuesten Datenbank
  • ManuellBeide Änderungsprotokolle (normalerweise sind die Änderungen nicht so groß, und wenn sie es sind, erfüllen sie normalerweise einen der Mängel des Diff- Befehls von Liquibases .
  • Erstellen Sie einen Änderungssatz

Selbst bei komplizierten Änderungen, bei denen eine benutzerdefinierte Änderung implementiert werden muss , kann dies in wenigen Stunden erreicht werden, einschließlich der Definition von Rollbacks, Tests und Dokumentation. Für triviale Änderungen ist es eine Frage von Minuten. Grundsätzlich gilt: Sie müssen etwas mehr Arbeit leisten (ich habe in weniger als einem Tag benutzerdefinierte Änderungssätze für 4 Datenbankkonfigurationen erstellt), aber Sie können sicher sein, dass Sie alles getan haben, um die Datenbank in einem konsistenten Zustand zu halten.

Markus W Mahlberg
quelle
1
Liquibase ist großartig, und für ein Produkt, das von einem Team festgelegt und entwickelt wird, ist das eine hervorragende Idee. Wenn Sie jedoch ein Einzelentwickler sind, einen Prototyp erstellen, die Grundlagen ausarbeiten oder auf andere Weise etwas erforschen, das sehr stark abwandern wird, ist es sehr wertvoll, es bei der Bereitstellung schnell in Sekunden anstatt in Minuten oder Stunden zum Laufen zu bringen. In der Regel sollte hbm2ddl.auto entfernt werden, sobald es einen QS-Datensatz gibt oder wenn Sie Produktionsdaten haben. Dumm zu sagen, wie auch immer, ist böse.
Gus
@Gus "nichts ist definitiver als das temporäre" ;) Und etwas, das Sie wirklich übersehen zu haben scheinen "(Wenn es als Tool für das Datenbankänderungsmanagement missbraucht wird)" Die Frage besagt eindeutig, dass es sich um Bereitstellungen handelt und daher um DB Change Management der Kontext hier. Und ich halte an meiner Aussage fest: Für den Einsatz sind beide a absolut böse. Übrigens, auch als Einzelentwickler ist Liquibase keine Arbeit mehr. Auf lange Sicht ist es weniger.
Markus W Mahlberg
Das ist albern und ziemlich wenig hilfreich. Für einfache automatisierte Tests hbm2ddlist es für die meisten Menschen ein vollkommen adäquates Werkzeug.
Gavin King
Nun, und wie stellen Sie sicher, dass Ihr Produktionssetup auf Ihr Entwicklungssetup migriert wird? Feuer und beten?
Markus W Mahlberg
Sie haben ein nützliches Werkzeug genannt, das ich geschrieben habe und das Hunderttausende von Menschen seit fast zwei Jahrzehnten erfolgreich als "böse" bezeichnet haben. Dass es nicht die Komplettlösung für jedes einzelne Problem im Datenmanagement ist, macht es nicht "böse".
Gavin King
8

Nachdem ich ein paar Stunden damit gestolpert war, beschloss ich zu teilen, was ich gefunden habe, obwohl es ein sehr alter Beitrag ist.

Damit es richtig funktioniert, musste ich Folgendes tun:

  • hbmddl einstellen create oder setzencreate-drop
  • file.sql im Klassenpfad root; In meinem Fall habe ich es einfach reingelegtresources Ordner gelegt, ich benutze Maven.
  • Jeder SQL-Befehl in einer Zeile
  • Jede file.sql muss am Anfang der Datei eine leere Zeile haben ==> kenne den Grund für diese nicht, aber wenn ich diese leere Zeile nicht einfüge, sagen mir die Server zum Zeitpunkt der Ausführung, dass es eine gibt Syntaxfehler in der Nähe des ersten Zeichens.

Hoffentlich hilft das.

Jomar
quelle
4
Die "First-Line-Ausgabe" klingt wie Stückliste
dtrunk
1
Ich denke du meinst import.sql, nicht file.sql.
Koray Tugay
Mit "file.sql" meinte ich jede * .sql-Datei, vergiss den Namen, solange du ihn in der Persistenzdatei angibst. import.sql ist der Name der standardmäßig importierten Datei (falls vorhanden), ohne dass diese in der Persistenzdatei angegeben werden muss.
Jomar
0

Bitte stellen Sie sicher, dass Ihre import.sql korrekt formatiert ist. Beginnen Sie mit einer Einzeiler-Einfügeanweisung zum Testen.

Ninja420
quelle
0

Die Standardmethode in JPA ist die Verwendung der Konfigurationseigenschaft javax.persistence.sql-load-script-source.

Sie können verschiedene Einstellungen für den Schemaexport und den Testdatenimport untersuchen, die in der AvailableSettingsKlasse von Hibernate aufgeführt sind .

Gavin King
quelle