# JPA/Eclipselink: DB Schema anlegen?



## tuxedo (2. Jan 2011)

Hallo zusammen,

hab mal ne Frage zu JPA bzw. Eclipselink: Hab da ein kleines, selbstgestricktes Serverframework das JPA mit Eclipselink verwendet und ich frage mich gerade, wie man am besten mit dem anlegen des DB Schemas umgeht?

Eclipselink kennt ja über die persistence.xml folgende Property:


```
<property name="eclipselink.ddl-generation" value="create-tables"/>
```

Das funktioniert prima. Beim Programmstart werden dadmit alle notwendigen Tabellen angelegt.

Aber beim zweiten start sind die Tabellen ja schon da und Eclipselink probiert nun nochmal die Tabellen anzulegen und vom darunterliegenden JDBC bekomm ich dann ne Exception dass der Create-Befehl fehlgeschlagen ist. Ist eigentlich nicht tragisch, aber sehr unschön.

Meine Frage ist jetzt:

Wie macht man das normalerweise? Lässt man JPA die Tabellen anlegen und ignoriert bei jedem weiteren Start die Fehlermeldungen? Oder liefert man das DB Schema selbst und stellt die obige property auf "none"?

Oder gibts irgendwo eine versteckte Property die nach dem Prinzip "Create only if tables do not exist" arbeitet?

- Alex


----------



## Gelöschtes Mitglied 5909 (2. Jan 2011)

Using EclipseLink JPA Extensions (ELUG) - Eclipsepedia

SIeht nicht so aus als ob es sowas gibt. Ich würde das Schema glaub ich liefert (ggf als script).


----------



## tuxedo (2. Jan 2011)

Jop, scheint nix zu geben. Aber irgend ein "Standardvorgehen" muss es doch geben, oder seh ich hier ein Problem das gar eins ist?

Ich mein, es ist ja schon elegant dass Eclipselink die Tabellen selbst anlegen kann. 

Wenn ich dann eine Serveranwendung fertig gebaut habe, warum sollte ich dann nochmals "Aufwand" spendieren müssen um bei der Installation der Serveranwendung das Db Schema anhand eines SQL Scripts anzulegen?

Ergibt für mich keinen Sinn ???:L


----------



## Herr K. (2. Jan 2011)

Hallo Alex,

es gibt kein echtes "Standardvorgehen". Ganz im Gegenteil kann man eben nicht ohne weiteres pauschal einen Ansatz als "besser" oder "schlechter" bezeichnen. Das wäre ein wenig wie die Wahl des Datenbanksystems, des Betriebssytems oder der Programmiersprache. Alles eine Frage der Anforderungen und mit unterschiedlichen Vor- und Nachteilen verbunden.

*Verwendung von SQL Skripten vs Anlegen durch die Applikation*
Für das Anlegen der Datenbankstruktur durch die Anwendung spricht, wie Du schon sagtest, eine gewisse Einfachheit. Die Pflege reduziert sich auf die Persistenzklassen und die enthaltenen Annotationen. Ein weiterer Vorteil ist sicherlich auch, dass Du keine Rücksicht auf den SQL Dialekt nehmen musst (z.B. ob man den Datentypen Datetime für Transact SQL oder Timestamp für SQLPlus benötigt). 
Legst Du die Datenbankskripte selbst an, hast Du hier den Vorteil, dass Du auf besondere Eigenschaften des SQL Dialekts eingehen kannst und die volle Kontrolle besitzt. Ein ganz einfaches Beispiel ist hier der Indextyp. Ein O/R Mapper kann nur anhand eines statischen Regelwerks seine Auswahl treffen. Ob Du eine Hashfunktion (gezielte Suche nach einzelnen Daten) oder doch einen B-Baum benötigst, ob die Suche über mehrere Eigenschaften erfolgt und Du eher einen R-Baum nehmen solltest kann der O/R Mapper nicht ohne weiteres entscheiden, hängt halt von der Nutzung ab. Vor allem aber kennt auch nicht jedes DBS alle diese Typen.

Was Du auch bedenken musst ist, dass Du getrennte Kompetenzen hast. Viele Firmen haben einen Datenbankadministrator, der nichts mit dem Systemadministrator zu tun hat, der die Applikation deployed. Hier kann es sein, dass der DB Admin gerne die Skripte zu einem beliebigen Zeitpunkt einspielen möchte und nur bestimmte Rechte auf dem zugehörigen Schema erteilt. 

Noch wichtiger und von Dir (glaube ich) noch nicht bedacht, wie möchtest Du denn auf Änderungen am Datenbankschema reagieren? Es kommt schon mal vor, dass man eine Spalte zu einer Tabelle hinzufügt oder eine Restriktion ergänzt bzw. einen Index hinzufügt. Erkennt der O/R Mapper nun, dass die Tabelle schon existiert, dann wird der nicht weiter prüfen ob die Struktur 1:1 übereinstimmt. Hier können ggf. einfach dem Nutzer schon die Rechte fehlen um die Metadaten auszulesen, an sich wäre das aber ein recht hoher Overhead wenn man davon ausgeht, dass i.d.R. keine Abweichung vorliegt. Für den Fall einer Änderung hast Du nun aber ein Problem. 
Genauso macht man gerne vor Änderungen an dem Datenbankschema (besonders wenn es schon Bestandsdaten gibt) möchte man gerne ein Backup des Schemas erzeugen. Das alles geht einfacher, wenn man explizit Skripte ausliefert die durch einen DB Admin eingespielt werden (das muss natürlich koordiniert erfolgen).



			
				tuxedo hat gesagt.:
			
		

> Wenn ich dann eine Serveranwendung fertig gebaut habe, warum sollte ich dann nochmals "Aufwand" spendieren müssen um bei der Installation der Serveranwendung das Db Schema anhand eines SQL Scripts anzulegen?



Nun ja, neben der schon gegebenen Motivation hast Du hier eigentlich schon eine wichtige Unterscheidung benannt. Die Installation und der Betrieb einer Anwendung sind zwei getrennte Sachen. Die Installation erfolgt initial und ist eher einmalig (für eine Programmversion). Wenn Du einen Webbrowser installierst, wird auch eine Menge gemacht (was auch etwas Zeit in Anspruch nimmt) und danach kannst Du den beliebig oft starten ohen jedes mal den Ablageort angeben zu müssen oder zu warten bis alle Daten dort hinkopiert wurden. 
Für eine Serveranwendung sieht das natürlich nicht anders aus. Auch hier kannst Du eine Installationsroutine vorsehen, welche die Tabellen anlegt. Unter der Voraussetzung, dass Du exklusiv auf einem Schema arbeitest, dass leer ist, würde Dich sicherlich die Ausnahme interessieren und auch sinnvoll erscheinen. Natürlich kannst Du auch explizit die Tabellen vorher löschen (hier gilt es dann eben sicherzustellen, dass nicht versehentlich doch eine Parallelinstallation, die ggf. produktiv ist, zerstört wird).
Entsprechend könntest Du einen Java Installer verwenden, der die Tabellenstruktur erzeugt. Neben einem "echten" Installer kann das natürlich auch eine getrennte Anwendung sein, die eben nur die DB Struktur erzeugt, aber eben vom Systemstart losgelöst ist (und eben eigene Properties verwendet).


----------



## Gelöschtes Mitglied 5909 (2. Jan 2011)

noch ne möglichkeit wäre eine art setup webanwendung, wird bei diversen webapps auch häufiger gemacht


----------



## maki (2. Jan 2011)

Stimme Herr K. da voll zu 

IMHO sind die einzige sinnvolle Anwendungsmöglichkeit für automatisch erstellte DB Schemas Integrationstests, aber nicht für den Prod. Betrieb.


----------



## tuxedo (3. Jan 2011)

@Herr K.

Danke für die ausführliche Antwort.



> Für das Anlegen der Datenbankstruktur durch die Anwendung spricht, wie Du schon sagtest, eine gewisse Einfachheit. Die Pflege reduziert sich auf die Persistenzklassen und die enthaltenen Annotationen. Ein weiterer Vorteil ist sicherlich auch, dass Du keine Rücksicht auf den SQL Dialekt nehmen musst (z.B. ob man den Datentypen Datetime für Transact SQL oder Timestamp für SQLPlus benötigt).



Das ist genau der Grund warum ich die Tabellen gerne automatisch anlegen lassen möchte. 
Den umgekehrten Weg möchte ich möglichst vermeiden (was bisher eigentlich recht gut klappt).


> Was Du auch bedenken musst ist, dass Du getrennte Kompetenzen hast. Viele Firmen haben einen Datenbankadministrator, der nichts mit dem Systemadministrator zu tun hat, der die Applikation deployed. Hier kann es sein, dass der DB Admin gerne die Skripte zu einem beliebigen Zeitpunkt einspielen möchte und nur bestimmte Rechte auf dem zugehörigen Schema erteilt.



Da hast du natürlich recht. Aber nicht jeder Anwendung die eine Datenbank benötigt, setzt auf eine existierende DB Installation auf. Hier kommt es doch sehr auf den Anwendungsfall an. Es gibt ja durchaus dedizierte Maschinen/Serverkisten, die nur eine einzige Aufgabe erledigen, und damit auch nur einen einzige /große) Serveranwendung laufen haben. Oftmals werden die auch als "Blackbox" verkauft: Auspacken, anschließen, läuft. Oder: CD in Servermaschine einlegen, System installieren lassen, läuft. Einen extra DB Admin gibt es da nicht. 

Aber gut, es gibt natürlich auch jede Menge Szenarien in denen eine Serveranwendung in ein bestehendes System integriert werden muss, und dann zwei Anwendungen da sind die beide MySQL oder Postgres oder sonstwas benutzen. 

Zuguter letzt gibts noch die Systeme mit den Embedded DBs. Und zu denen zählt mein System.



> Noch wichtiger und von Dir (glaube ich) noch nicht bedacht, wie möchtest Du denn auf Änderungen am Datenbankschema reagieren?



Doch doch, bedacht habe ich das schon. Und um da äußerst flexibel zu sein, dachte ich da an einen Datenexport und -Import der bei einem Systemupdate gefahren wird. Das ist zwar etwas Aufwand, aber 1. Ich hab ein unabhängiges Backup der Daten (CSV, XML oder wie auch immer) und 2. ich kann mit der nächsten Version des Servers wenn ich will eine ganz andere Persistenz-Technik einsetzen. Bin also "etwas" flexibler.



> Für eine Serveranwendung sieht das natürlich nicht anders aus. Auch hier kannst Du eine Installationsroutine vorsehen, welche die Tabellen anlegt.



Ich denke sowas in der Art werde ich auch umsetzen. Eclipselink kann ja alternativ zum anlegen der Tabellen in der DB ein SQL-Script erstellen. Am besten wäre es halt, wenn man das außerhalb der Serveranwendung triggern könnte, so dass man es in einen Maven-Build-Prozess mit einbaut:

1.) Serveranwendung compilieren und das fertige Anwendungspaket vorbereiten
2.) DB Schema aus den bestehenden Entities extrahieren und SQL-Script anlegen
3) Artefakte aus 1) und 2) zusammen mit einem Installer verheiraten. Fertig.

Das einzige was mich daran stört: Die Serveranwendung ist modular und kann zur Laufzeit mit weiteren Modulen (von Dritten) nachgerüstet werden. Und diese Module können auch Entities haben. Und hier schlägt dann wieder das "Problem" zu: "Create if not already exist"....(was so von Eclipselink nicht vorgesehen ist :-( ). 

Vielleicht finde ich für diesen Anwendungsfall doch noch 'nen Weg der die Fehlermeldung von wegen "Du Trottel, die DB existiert schon" verhindert...


Gruß 

Alex

P.S.
@Rail
Ja, das wäre eine Idee...Auch für das Nachrüsten von Modulen. Ein Upload via Webpage der die Tabellen anlegt, anpasst, und dann das Modul im Server deployed.

[update]
Hab gelesen Hibernate kennt einen "update" Modus der das Schema sogar "aktualisieren" kann. Eclipselink hingegen kennt sowas gar nicht. *sehr schade*
Was mich aber noch mehr irritiert: Eclipselink kann das Schema in eine SQL-File schreiben.... Hatte ich ja schon erwähnt. Aber wo braucht man sowas zur Laufzeit?! Ich mein: Nehmen wir mal an wir haben einen JEE Server der Eclipselink benutzt. Und ich deploye ne neue Anwendung die ihre eigenen Entities mitbringt. Hier wäre in der Tat so eine Update-Funktion sinnvoll. Das Schema dann in eine SQL-File schreiben zu lassen bringt einen (im Betrieb) nicht weiter. Denn ich will ja die Tabelle haben. Und spätestens wenn die Anwendung undeployed und mit einer neueren Version verseen wird, wäre eine Update-Funktion sinnvoll. Aber nein. Hier muss man entweder selbst hand anlegen (Update SQL-Files VOR dem deployen ausführen), ODER man spendiert noch mehr aufwand und bastelt sowas hier: On Persistence: Running a SQL Script on startup in EclipseLink

Alles in allem: Ich denke für solche Szenarien könnte Eclipselink noch mehr tun. Nur bringt mich das jetzt nicht der Lösung näher :-(


----------



## tuxedo (4. Jan 2011)

Sodele,

ich hab jetzt mal testweise auf Hibernate umgesattelt. Musste nur meine persistence.xml anpassen und die benötigten Libs in den Classpath werfen. Und siehe da: Funzt ;-)

Und hier gibts nun die Property:


```
<property name="hibernate.hbm2ddl.auto" value="update"/>
```

Damit wird

1) das Schema bei Bedarf angelegt
2) das Schema bei Bedarf aktualisiert
3) Nicht jedesmal eine Fehlermeldung geworfen wenn das Schema schon da ist (dafür bekomm ich anderen Info-Logoutput :-( )

Alles in allem: Ich glaube für meinen Anwendungszweck fahr ich mit Hibernate besser. Und wie ich gelesen habe, soll Hibernate ja nun auch JPA2.0 kompatibel sein. Eclipselink ist zwar die Referenzimplementierung, aber Hibernate hat wohl die größere Community, womit ich mal frei heraus vermute, dass Hibernate da nicht wirklich schlechter sein kann. 

Ich muss nun also kein SQL Script generieren lassen, welches ich bei der Instalation vor dem ersten Serverstart in die DB importiere um die Tabellen zu erzeugen. Und ich kann zur Laufzeit Module in den Server deployen, welche dann dank Hibernate ihre Tabellen selbst anlegen und ggf. aktualisieren, OHNE dass ich mit Fehlermeldungen bombardiert werde (eben so wie man es u.A. von JBoss kennt wenn man eine Anwendung platziert).

Und zuguter letzt: Eclipselink funktioniert auch weiterhin. Ich muss nur die persistence.xml anpassen. Und Modul A kann wenn es lustig ist Hibernate benutzen und Modul B dann Eclipselink.

Flexibler geht's dann wohl nicht mehr.

Mich würde da aber nach wie vor eure Meinung dazu interessieren...

Gruß
Alex


----------



## Gelöschtes Mitglied 5909 (5. Jan 2011)

Hast du mal versucht das in OSGi zum laufen zu bringen 

Willst/musst du warscheinlcih nicht, von daher warum auch nicht 

Ich würde an deiner stelle nur nicht zwischen HN und EL mischen.


----------



## tuxedo (6. Jan 2011)

Naja, Mischbetrieb ist hier eher nicht der Regelfall. Werde wenn, dann nur eine JPA Implementierung. Aber in der theorie müsste auch beides gleichzeitig funktioniere. Die Module laufen ja mit eigenen Classloadern, eigenen Entitymanagern und eigenen persistence.xml's.


----------

