JPA mit Apache Derby als Eclipse Tutorial

-- Nur für Programmierer gedacht --
-- Also available in english --

Ich arbeite an einem kleinen Projekt, welches extensiven Gebrauch von Informationen aus der Wikipedia macht und wenn letztendlich auch nur ein kleiner Punkt auf einer Karte rauskommen soll, so wird eine Menge Text geladen, durchsucht, gespeichert - bis mir ein Heap-Overflow erstmal den Spaß verdorben hat.

Jetzt war meine Lust einen Datenbankadapter zu schreiben eher von wenig Enthusiasmus getrieben.
Als Lösung mit wenig Arbeitsaufwand bot sich da JPA (Java Persistence API) an. Das Grundprinzip baut darauf auf Java-Klassen auf Datenbanktabellen abzubilden. Man sorgt sich nur um die Zuordnung, welche Klasse in welcher Tabelle und welche Instanzvariable in welchem Feld gespeichert wird und den Rest erledigt die Persistenzschicht.

Es existiert bereits ein JPA-Tutorial mit Beispiel-Dateien für Netbeans. Mein Ansatz ist der gleiche allerdings zeige ich für Eclipse wie man den Code aus dem vorher erwähnten Tutorial in Eclipse zum Laufen bringt.

Als Datenspeicher im Hintergrund dient Derby, welches vom Apache DB Projekt und letztendlich von der Apache Software Foundation gepflegt wird. Das Schöne an Derby ist, dass es für den Hausgebrauch ist. Als leichtgewichtige Datenbank wiegt es gerade mal 2 MB und Wartung und Installation erfordern auch keinen eigenen Universitätsabschluss.

Eine kleine Auflistung der zu erledigenden Aufgaben:

  1. Runterladen der benötigten Dateien
  2. Installation der Eclipse-Plugins
  3. Einrichtung des Eclipse-Projekts

So. Genug der Worte - auf geht's.


Download der benötigten Dateien

Als erstes sollte man sich folgende Datei JPA_Apache_Derby.zip (6,2 MB) runterladen. Darin enthalten sind 2 Eclipse-Plugins und das Eclipse-Beispielprojekt. Die Plugins sorgen für die Integration von Derby in Eclipse.
Also speichert man die Datei am besten im Eclipse Workspace und entpackt das darin enthaltene Verzeichnis.


Installation der Eclipse-Plugins

Danach sollte man die Plugins installieren. Dazu entpackt man die im Ordner "JPA Apache Derby" enthaltene
derby_core_plugin_10.3.1.zip und genauso die derby_ui_plugin_1.1.1.zip. Den entpackten Ordner "plugins" kann man dann getrost in das Eclipse Stammverzeichnis kopieren, wo sich schon der entsprechende "plugins"-Ordner befinden sollte. Danach sollte man das Eclipse Projekt aus der Datei "JPA_Eclipse.zip" entpacken. Dabei entsteht der Ordner "JPA_Eclipse".
So oder so ähnlich sollte der Ordnerinhalt danach aussehen:


Einrichtung des Eclipse-Projekts

Als nächstes öffnet man Eclipse, dabei sollte es keine Fehlermeldungen geben. Von den installierten Plugins sieht man erstmal nicht viel. Der Clou ist, dass man per Rechtsklick Projekten nun eine "Apache Derby Nature" hinzufügen kann.

Dann importiert man das Projekt "JPA_Eclipse", welches sich ebenfalls in dem entpackten "JPA Apache Derby" Ordner befunden hat.

Nach einem Rechtsklick in den Package Explorer, wählt man "Import" und dann "Existierendes Projekt in den Workspace"


Voila... Jetzt geht es ans eingemachte.


Start von Derby

Das importierte Projekt hat schon die oben angesprochene "Apache Derby Nature". So sieht man nach einem Rechtsklick auf das Projekt weiter unten im Kontextmenü den Eintrag "Apache Derby". Dort wählt man dann die Option "Start Derby Network Server".

Als nächstes wird folgende Meldung ausgegeben.

Und die Konsole sollte den Start folgendermaßen quittieren.

DRDA_SecurityInstalled.I
Apache Derby Network Server 10.3.1.4 - (561794) wurde gestartet und ist seit 2007-11-22 21:25:03.773 GMT bereit, Verbindungen am Port 1527 zu akzeptieren.


Erzeugen einer Derby-Datenbank und der Tabellen

Im Projekt finden sich im Ordner "sql" die Dateien "createDatabase.ij" und "tables_derby.sql". Diese öffnet man über das Rechtsklick-Kontextmenü am besten mit dem Text-Editor. Darin stehen Befehle, die wir in den folgenden Schritten benötigen.

Ein weiterer Rechtsklick auf das Projekt und danach startet man über "Apache Derby" -> "ij (Interactive SQL)" die interaktive SQL-Konsole.

Als erstes fügt man nun die Zeile aus der Datei "createDatabase.ij" im ij ein:

connect 'jdbc:derby://localhost:1527/testDB;create=true;user=APP;password=APP';


Dadurch stellt man eine Verbindung zur Datenbank "testDB" her oder erstellt diese, wenn sie noch nicht existiert. Username und Passwort sollten erstmal nicht verändert werden.

Danach fügt man den Inhalt aus der Datei "tables_derby.sql" in die Konsole ein. Allerdings nicht alles auf einmal! Am Besten jede der vier Anweisungen für sich, sonst läuft man Gefahr, dass sich ij verschluckt und man wird später die Fehlermeldung bekommen, dass die Tabelle "ORDER_TABLE" nicht gefunden wurde.

I)

drop table ORDER_TABLE;

II)

drop table CUSTOMER;

III)

create table CUSTOMER (
ID NUMERIC(10) PRIMARY KEY,
NAME VARCHAR(256)
);

IV)

create table ORDER_TABLE (
ORDER_ID NUMERIC PRIMARY KEY,
SHIPPING_ADDRESS VARCHAR(500),
CUSTOMER_ID NUMERIC(10),
FOREIGN KEY (CUSTOMER_ID) REFERENCES CUSTOMER (ID)
);


Speichern der Tabellen-Definitionen

Danach verabschiedet man sich aus ij mit dem Befehl:

disconnect ALL;

Nun sollte man Derby stoppen, dazu braucht es nichts weiter als die rechte Maustaste -> "Apache Derby" -> "Stop Derby Network Server"

Die Konsole sieht nachher folgendermaßen aus:

DRDA_SecurityInstalled.I
Apache Derby Network Server 10.3.1.4 - (561794) wurde gestartet und ist seit 2007-11-22 21:45:19.857 GMT bereit, Verbindungen am Port 1527 zu akzeptieren.
Apache Derby Network Server 10.3.1.4 - (561794) wurde heruntergefahren am 2007-11-22 21:50:43.998 GMT.

Der ij-Prozess beendet sich nicht selbstständig und blockiert weitere Zugriffe auf die Datenbank, also wechselt man in die Debug-Ansicht und beendet den ij Prozess manuell.


Derby-Neustart

Jetzt ist es so gut wie geschafft. Nur noch einmal Apache Derby starten (Rechtsklick Project -> "Apache Derby" -> "Start Derby Network Server").


Start des JPA-Testprogramms

Jetzt startet man das Testprogramm indem man mit der rechten Maustaste auf die Datei Client.java im Ordner Source/client klickt und danach "Debug As" -> "Java Application" auswählt.

Das Testprogramm erzeugt folgende Ausgabe, dabei werden die entsprechenden Daten ("Joe Smith") gespeichert und am Ende des Programms wieder aus der Datenbank gelöscht. Also ohne Breakpoints an den richtigen Stellen bekommt man von der ganzen Pracht wenig mit.

Ausgabe:

[TopLink Config]: 2007.11.22 10:45:21.982--ServerSession(13037557)--The alias name for the entity class [class entity.Customer] is being defaulted to: Customer.
[TopLink Config]: 2007.11.22 10:45:22.008--ServerSession(13037557)--The table name for entity [class entity.Customer] is being defaulted to: CUSTOMER.
[TopLink Config]: 2007.11.22 10:45:22.023--ServerSession(13037557)--The column name for element [public java.lang.String entity.Customer.getName()] is being defaulted to: NAME.
[TopLink Config]: 2007.11.22 10:45:22.039--ServerSession(13037557)--The column name for element [public int entity.Customer.getId()] is being defaulted to: ID.
[TopLink Config]: 2007.11.22 10:45:22.057--ServerSession(13037557)--The alias name for the entity class [class entity.Order] is being defaulted to: Order.
[TopLink Config]: 2007.11.22 10:45:22.159--ServerSession(13037557)--The target entity (reference) class for the one to many mapping element [public java.util.Collection entity.Customer.getOrders()] is being defaulted to: class entity.Order.
[TopLink Config]: 2007.11.22 10:45:22.163--ServerSession(13037557)--The target entity (reference) class for the many to one mapping element [public entity.Customer entity.Order.getCustomer()] is being defaulted to: class entity.Customer.
[TopLink Config]: 2007.11.22 10:45:22.172--ServerSession(13037557)--The primary key column name for the mapping element [public entity.Customer entity.Order.getCustomer()] is being defaulted to: ID.
[TopLink Info]: 2007.11.22 10:45:22.643--ServerSession(13037557)--TopLink, version: Oracle TopLink Essentials - 2006.8 (Build 060830)
[TopLink Config]: 2007.11.22 10:45:23.548--ServerSession(13037557)--Connection(5535614)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.555--ServerSession(13037557)--Connection(24298619)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.556--ServerSession(13037557)--Connection(29460424)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.563--ServerSession(13037557)--Connection(2707298)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.563--ServerSession(13037557)--Connection(1752967)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.571--ServerSession(13037557)--Connection(1331389)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.571--ServerSession(13037557)--Connection(29408998)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.575--ServerSession(13037557)--Connection(20259911)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.575--ServerSession(13037557)--Connection(31517012)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.579--ServerSession(13037557)--Connection(16164994)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.579--ServerSession(13037557)--Connection(28378327)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.586--ServerSession(13037557)--Connection(11850652)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Config]: 2007.11.22 10:45:23.586--ServerSession(13037557)--Connection(28365628)--connecting(DatabaseLogin(
platform=>JavaDBPlatform
user name=> "APP"
datasource URL=> "jdbc:derby://localhost:1527/testDB"
))
[TopLink Config]: 2007.11.22 10:45:23.590--ServerSession(13037557)--Connection(33310350)--Connected: jdbc:derby://localhost:1527/testDB
User: APP
Database: Apache Derby Version: 10.3.1.4 - (561794)
Driver: Apache Derby Network Client JDBC Driver Version: 10.3.1.4 - (561794)
[TopLink Info]: 2007.11.22 10:45:23.639--ServerSession(13037557)--file:/C:/Users/Stefan%20Linke/Desktop/Apache%20Derby/JPA_Eclipse/bin-pu1 login successful
Inserting Customer and Orders... OK
Verifying that all are inserted... OK
Removing all... OK
Verifying that all are removed... OK

Das wars...

Comments

Connect zur Datenbank

Woher weiß der Client zu welcher Datenbank er verbinden muss, hier TestDB.
Kann man diesen Connect zur Datenbank explizit im Sourcecode definieren, wenn ja wie?

Persistence.xml

Schau mal in /Source/META-INF/persistence.xml.
Viele Grüße
Stefan

Eclipse Version?

Hallo Stefan,

welche Eclipse-Version hast du verwendet? Die Eclipse-Ui Teile scheinen in 3.4.2 (Ganymede) nicht mehr zu laufen. Im Kontextmenü des Projektes erscheint "Apache Derby" nicht und dadurch auch die Derby nature nicht.

hast du eine Idee?

Gruß
Martin

Eclipse Version

Hallo Martin,

ich habe das zu Zeiten von Eclipse 3.2.2 erstellt. Leider habe ich nicht genug Zeit um mir das Ganze unter 3.4.2 anzuschauen.

Viele Grüße
Stefan

Hi, schöner Guide nur leider

Hi,

schöner Guide nur leider funkioniert es bei mir mit 3.4.1 auch nicht obwohl ich die neuesten Versionen vom core und ui-plugin habe.
Naja, vielleicht bekomme ich es noch zum Laufen.

Gruß