# Hibernate/H2: Datenbank bei Erststart erzeugen



## resTive (5. Okt 2009)

Hallo,

ich experimentiere gerade ein wenig mit hibernate, und versuche ein Gefühl dafür zu kriegen. Ich möchte nun erreichen, dass meine (absolut fiktive) Applikation bei ihrem Start prüft ob die Datenbank vorhanden ist oder nicht. In letzterem Fall soll diese automatisch anhand des Schemas, welches (wenn ich das richtig verstanden habe) zuvor schon durch das mapping festgelegt wurde, erstellt werden.

Nach dem ich jetzt eine weile rumprobiert und gelesen habe bin ich auf folgendes das property hibernate.hbm2ddl.auto gestoßen. :rtfm:???:L

die werte für diese property sind wenn ich sie richtig verstanden habe

create: erzeugt einmalig beim starten der ersten session ein neues schema.
create-drop: erzeugt für jede session die datenbank und löscht diese wenn die session beendet wurde
*update: passt das schema bei Änderungen an.*
validate:  kann ich mir keinen richtigen reim drauf machen (als nebenfrage: wofür ist validate gedacht?) 

das update scheint mir genau das richtige zu sein, aber auch nur dann, wenn die Datenbank bereits existiert. 

Wie stelle ich es also an, dass mir die eine Datenbank erstellt wird, wenn die Applikation keine unter der konfigurierten connection.url finden kann? oder ist das mit hibernate garnicht möglich, und ich muss sie selbst erstellen?

wäre super, wenn mir da wer weiterhelfen kann.


----------



## byte (6. Okt 2009)

Hätte jetzt gedacht, dass es mit update funktioniert. Aber wenns so ist wie Du sagst, dann kannst Du den Prozess auch manuell anstoßen, z.b. mit Ant:

Chapter 20. Toolset Guide


----------



## -MacNuke- (6. Okt 2009)

Wie wäre es mit Create?


----------



## resTive (6. Okt 2009)

byte hat gesagt.:


> Hätte jetzt gedacht, dass es mit update funktioniert. [...]



hm, hatte ich auch gedacht. allerdings habe ich unter anderem im hibernate forum und auf stackoverflow immer wieder gelesen das update in produktionsumgebungen nicht benutzt werden soll weil a) kein entwickler (selbst hibernate devs) dem nicht 100% trauen würden und b) soll es auch nicht mehr gewartet werden (siehe hier) allerdings ist der post von 2003 :autsch:



byte hat gesagt.:


> [...]Aber wenns so ist wie Du sagst, dann kannst Du den Prozess auch manuell anstoßen, z.b. mit Ant:
> 
> Chapter*20.*Toolset Guide



von ant habe ich allerdings auch (noch) garkeine ahnung. gehe ich recht der annahme, dass du mir vorschlägst im final build per ant eben jene (leere) datenbank anzulegen und mit auszuliefern? 

in genau dem genannten thread habe ich auch hibernate.hbm2ddl.auto=create-update gefunden, das auch genau das macht, was man erwarten würde (erzeugen oder verwenden). allerdings sagt auch dazu der entwickler in dem selben thread dass das eigentlich nicht funktionieren dürfe und er es mysteriös finden ;(


ja verdammt, ich kann doch nicht der einzige entwickler auf der welt sein der eine anwendung verteilen will, welches eine emedded datenbank benutzt, die beim start noch keine daten enthält...

weil so fiktiv ist die anwendung nicht mehr, nachdem ich da jetzt ne weile rumprobiert und gemacht und getan habe, habe ich schon ein konkretes projekt vor augen (RCP+JavaWebStart+Hibernate/H2), wo ich das verdammt gut gebrauchen kann... allerdings möchte ich dieses problem, und auch andere, gelöst haben bevor ich überhaupt mit der planung anfange.


also weiterhin sind hilfen anmerkungen, links erwünscht, die mir das licht am ende des tunnels zeigen könnten 

*EDIT*


-MacNuke- hat gesagt.:


> Wie wäre es mit Create?



create ist während der entwicklung nicht verkehrt richtig, in der produktion wäre es allerdings fatal, wenn ich bei jedem start diese datenbank lösche


----------



## byte (6. Okt 2009)

Über die Güte von hbm2ddl kann ich Dir nichts sagen. Wir machen es so, dass wir uns die DDL von Hibernate erzeugen (also nur das Script), diese dann noch manuell anpassen und dann das Schema manuell mit einem DB Tool aufspielen.

Mir fällt jetzt aber auch kein Grund ein, warum man das bei einer Embedded DB nicht direkt mit hbm2ddl machen sollte, wenn die erzeugte DDL im Test einwandfrei funktioniert.


----------



## -MacNuke- (7. Okt 2009)

resTive hat gesagt.:


> create ist während der entwicklung nicht verkehrt richtig, in der produktion wäre es allerdings fatal, wenn ich bei jedem start diese datenbank lösche



Also mir ist noch keine Datenbank untergekommen die bei einem CREATE TABLE die Tabelle löscht 

Das update kannst du vergessen. Funktioniert nicht immer.


----------



## Prismapanda (7. Okt 2009)

So wie ich das sehe, kann Hibernate die Datenbank selbst nicht anlegen (das war doch die Frage oder?), nur eben das zugrundelegende Schema. Dies kann dann mit den erwähnten Werten erfolgen. 'update' funktioniert in der Tat nicht immer richtig beim Aktualisieren eines Schemas, insbesondere wenns um Schlüssel und Collections geht. Im Erstellen der Tabelle arbeitet es aber IMO genauso wie 'create'.
Ich würde für Produktionsumgebungen empfehlen, das Schema zu exportieren und mittels eigenem Script einzuspielen. Dann kannst du die Datenbank dort anlegen, Schema einspielen und die Property auf 'none' setzen.
Für die Entwicklung nehme ich immer 'update', weil da die Daten drinbleiben und simple Änderungen (neue Variable etc.) mit eingespielt werden, ohne das Schema neu anzulegen.

Ich bezieh mich da jetzt mal auf den Thread https://forum.hibernate.org/viewtopic.php?p=2299145&sid=52f0ac9ed40120d9a6f0ab4f53fe2809. Der ist allerdings auch schon 3 Jährchen alt, aber es klingt zumindest so, als wär da keine Möglichkeit das zu ändern.
Wer neuere Infos hat - wäre für ein Update auch dankbar


----------



## resTive (10. Okt 2009)

entschuldigt, habe die neuen Posts heute erst gesehen. danke für eure antworten.

Da ich, wenn alles so läuft wie geplant, über die Verteilung dieser Anwendung keine Kontrolle haben werden, fällt ein manuelles anlegen der Datenbank aus. Und da es eine Delete&Forget Anwendung werden soll, soll alles von dem Programm benötigte angelegt  oder sonstwie zur Verfügung gestellt werden. Daher auch die lokale dateibasierte Datenbank H2 (oder HSQLDB, Derby) was auch immer...


nun da ich jetzt mehr oder weniger die restlichen tage meine freizeit für dieses Problem geopfert habe, die Datenbank automatisiert anlegen zu lassen, habe ich mich für die Variante des SchemaExport entschieden. Einzige problem, dass ich mit dieser Variante mehr oder weniger auf H2 festgelegt bin.

Da die Hibernate configuration ja in ihrer connection url ja auch den speicherort stehen hat, und ich weis, dass diese Datei mit '.h2.db' endet überprüfe ich, ob diese Datei im gewünschten Pfad vorhanden ist und wenn nicht, dann lege ich die Datei mit folgendem Snippet an.


```
AnnotationConfiguration config      = new AnnotationConfiguration();
config.configure();
config.setProperty("hibernate.connection.url", URL);
config.addAnnotatedClass(Clazz1.class);
config.addAnnotatedClass(Clazz2.class);
config.addAnnotatedClass(ClazzN.class);
factory = config.buildSessionFactory();
[b]new SchemaExport(config).execute(true, true, false, true);[/b]
```

da damit mein problem gelöst ist, ist die frage auch nicht mehr offen.

Danke für eure Hilfe


----------



## blublablo (5. Dez 2009)

Hi, ich stand auch mal vor diesem Problem und löse das Problem mit einer simplen SQL-Abfrage. Man kann nämlich die Tabellen nur anlegen lassen, wenn diese noch nicht existieren:

CREATE TABLE IF NOT EXISTS FILM (
    SPALTE1 VARCHAR(80),
    SPALTE2 VARCHAR(80),
    ...
);

Diese SQL lässt du jedes Mal bei Verwenden deiner Datenbank aufrufen. Die Tabellen werden dann nur erzeugt, wenn diese noch nicht existieren. H2 erzeugt übrigens völlig automatisiert die Datenbank, wenn diese noch nicht existiert, Beispiel:
[Java]
// Verbindung zur H2-Datenbank aufbauen
Connection h2Connection = DriverManager.getConnection("jdbc:h2:"C:\\H2Datenbank", "sa", "");
[/code]

Würde nun unter "C:" die Datenbankdatei "H2Datenbank.h2.db" anlegen, falls diese nicht existiert.

Grüße


----------



## maki (5. Dez 2009)

Wenn man JPA (oder ein anderes ORM) nutzt und die Entities Refactored, muss die DB Struktur & die Daten(!!!) auch refactored werden, für letzteres gibt es keinen automatismus


----------

