1. Einleitung
Das PDF dieses Dokuments ist |HIER|| verfügbar.
Die Beispiele in diesem Dokument sind |HIER| verfügbar.
1.1. Inhalt
In diesem Dokument schlagen wir vor, verschiedene Konfigurationen für den Einsatz von Datenbanken zu untersuchen. Betrachten Sie die folgende Schichtenarchitektur:
![]() |
Der Ausführungsablauf verläuft von links nach rechts:
- Zunächst wird eine der Klassen in der [ui]-Schicht (User Interface) ausgeführt. Diese instanziiert die [business]- und [DAO]-Schichten. Handelt es sich bei der [ui]-Schicht um eine grafische Benutzeroberfläche, wartet sie anschließend auf Benutzeraktionen. Eine Benutzeraktion kann die Ausführung von Methoden über alle Schichten der Architektur hinweg bis hinunter zur Datenbank auslösen. Das Ergebnis dieser Ausführungen wird dem Benutzer in der einen oder anderen Form zurückgegeben;
Die Rollen der verschiedenen Schichten könnten wie folgt aussehen:
- Die [JDBC]-Schicht (Java Database Connectivity) ist eine universelle Schnittstelle für den Datenbankzugriff. Sie stellt der [DAO]-Schicht stets dieselbe Schnittstelle zur Verfügung. Wenn Sie das DBMS wechseln, müssen Sie lediglich den JDBC-Treiber austauschen. Die [DAO]-Schicht bleibt unverändert, wenn Sie darauf geachtet haben, bestimmte Regeln einzuhalten. Es ist jedoch schwierig, eine 100-prozentige Portabilität zwischen DBMS zu gewährleisten, da diese oft eine beträchtliche Menge an proprietärem SQL enthalten, das schwer zu ignorieren ist, da es häufig Leistungsvorteile bietet. Sobald proprietäres SQL verwendet wird, ist die Portabilität zwischen DBMS nicht mehr möglich. Darüber hinaus haben DBMS oft unterschiedliche Richtlinien für die automatische Generierung von Primärschlüsseln sowie reservierte Schlüsselwörter, die von System zu System variieren. In diesem Dokument ist es uns dennoch gelungen, die untersuchte JDBC-Architektur auf sechs verschiedene DBMS zu portieren, indem wir akzeptiert haben, dass für jedes davon ein Konfigurationsprojekt erforderlich ist;
- die [DAO]-Schicht stellt eine Schnittstelle für den Zugriff auf Daten aus der jeweils verwendeten Datenbank bereit (im Unterschied zur JDBC-Schnittstelle, die für jedes DBMS gültige Methoden bereitstellt);
- Die [Business]-Schicht implementiert die Verwaltungsregeln oder Geschäftsregeln der Anwendung.
- Ihre Eingabedaten bestehen aus Daten aus der Datenbank über die [DAO]-Schicht und/oder Benutzereingaben, die von der [UI]-Schicht an sie übermittelt werden;
- Sie erzeugt Daten, die sie über die [DAO]-Schicht in der Datenbank speichern und/oder an die [UI]-Schicht zurückgeben kann, die sie abgefragt hat, um sie dem Benutzer anzuzeigen;
- Die [UI]-Schicht ist die Schicht, die die Aktionen des Benutzers ausführt und die Ergebnisse dieser Aktionen an den Benutzer zurückgibt;
Oben sendet die [DAO]-Schicht SQL-Abfragen an die [JDBC]-Schicht zur Ausführung im DBMS. In den letzten Jahren (seit 2006) hat sich diese Architektur wie folgt weiterentwickelt:
![]() |
Nun ist es die JPA-Schicht (Java Persistence API), die SQL-Abfragen an die JDBC-Schicht sendet und die Ergebnisse empfängt. Die [JPA]-Schicht übergibt Operationen an die [DAO]-Schicht, um Objekte zu speichern, zu ändern, zu löschen und abzurufen. Die [DAO]-Schicht gibt keine SQL-Befehle mehr aus. Dieser Ansatz ist portabler, da JPA-Implementierungen Unterschiede zwischen DBMS-Systemen abdecken, aber er ist langsamer als die JDBC-Technologie. Wir werden Leistungstests durchführen, um dies zu demonstrieren. Die JPA-Technologie formalisiert die Arbeit, die das Hibernate-Framework [http://hibernate.org/] bereits vor Jahren geleistet hat.
Wir werden zwei [DAO]-Schichten untersuchen, die eine der folgenden beiden Architekturen verwenden:
![]() |
![]() |
Wir werden verlangen, dass die Schichten [DAO1] und [DAO2] dieselbe [IDAO]-Schnittstelle implementieren. Somit wird der Test [JUnitTestsDao] für beide Konfigurationen identisch sein und es uns ermöglichen, die Leistung zu vergleichen. Die Schicht [DAO1] wird mit Spring JDBC und die Schicht [DAO2] mit Spring JPA implementiert;
Sobald dies erledigt ist, werden wir die [IDAO]-Schnittstelle wie folgt im Web verfügbar machen:
![]() |
- In [1] wird die [IDAO]-Schicht über eine von Spring MVC implementierte Webschicht [2] im Web verfügbar gemacht. Es ist tatsächlich die [IDAO]-Schnittstelle, die verfügbar gemacht wird, und wir werden zwei Versionen des Webdienstes erstellen, je nachdem, ob diese Schnittstelle unter Verwendung einer [DAO-JDBC]- oder einer [DAO-JPA-JDBC]-Architektur implementiert wird;
- In [B] nutzt ein Remote-Client die vom Webservice bereitgestellten URLs, die Zugriff auf die Methoden der [IDAO-Server]-Schicht bieten. Wir werden sicherstellen, dass die [DAO-Client]-Schicht [3] die [IDAO-Server]-Schnittstelle [1] implementiert. Dies ermöglicht es uns, denselben [JUnitTestsDao]-Test zu verwenden, der bereits zweimal verwendet wurde [4];
- In [3] wird die [DAO-Client]-Schicht unter Verwendung von Spring RestTemplate implementiert;
Sobald dies erledigt ist, werden wir den Zugriff auf den Webdienst sichern:
![]() |
- In [5] durchläuft die HTTP-Anfrage des Clients eine mit Spring Security implementierte Authentifizierungsschicht;
Sobald dies geschehen ist, werden wir die bisherige Architektur wie folgt weiterentwickeln:
![]() |
- In [3] ist die Client-Anwendung selbst eine Webanwendung. Sie wird über ein Formular [5] verfügen, über das Benutzer die URLs des sicheren Webdienstes abfragen können. Der HTTP-Zugriff auf den sicheren Webdienst wird über eine in JavaScript implementierte [DAO-client-js]-Schicht abgewickelt. Diese Architektur nutzt sogenannte domänenübergreifende Anfragen:
- Der Webdienst [2] stellt URLs der Form [http://machine1:port1/] bereit;
- die Client-Webanwendung [3] wird von einer URL [http://machine2:port2/] heruntergeladen. Wenn [http://machine2:port2/] nicht mit [http://machine1:port1/] identisch ist (gleicher Rechner, gleicher Port), blockiert der Client-Browser HTTP-Aufrufe aus der [DAO-client-js]-Schicht. Um dieses Problem zu beheben, muss der Webdienst domänenübergreifende Anfragen zulassen. Wir werden sehen, wie das geht;
Die vorgestellten Projekte wurden mit den folgenden sechs DBMS getestet:
- MySQL 5 Community Edition;
- SQL Server 2014 Express;
- PostgreSQL 9.4;
- Oracle Express 11g Release 2;
- IBM DB2 Express-C 10.5;
- Firebird 2.5.4;
Für jedes dieser DBMS haben wir vier verschiedene [DAO]-Schichten entwickelt:
- eine mit Spring JDBC implementierte Schicht;
- eine mit Spring JPA und dem Hibernate-JPA-Provider implementierte Schicht;
- eine mit Spring JPA und dem EclipseLink-JPA-Anbieter implementierte Schicht;
- eine mit Spring JPA und dem OpenJPA-JPA-Provider implementierte Schicht;
Somit wird hier eine Reihe von vierundzwanzig verschiedenen Konfigurationen vorgestellt. Wir haben uns sehr bemüht, den Code zu faktorisieren:
- Der Großteil des Codes wird nur einmal geschrieben. Er basiert auf zwei Maven-Konfigurationsprojekten:
- Das eine konfiguriert die JDBC-Schicht;
- das andere konfiguriert die JPA-Schicht;
![]() |
![]() |
Das Maven-Konfigurationsprojekt für die JDBC-Schicht [1] eines bestimmten DBMS umfasst zwei Schritte:
- Importieren des JDBC-Treiberarchivs;
- die Definition der Zugangsdaten für die verwendete Datenbank und der verschiedenen SQL-Anweisungen, die die [DAO1]-Schicht an den JDBC-Treiber sendet. Obwohl SQL standardisiert ist, stießen wir auf Portabilitätsprobleme, die hauptsächlich darauf zurückzuführen waren, dass Abfragen Tabellen- und Spaltennamen enthielten, die sich in bestimmten DBMS als verbotene Schlüsselwörter herausstellten (die Tabelle ROLES bei DB2, die Spalte PASSWORD bei Firebird). Darüber hinaus ist die Groß-/Kleinschreibung bei Spaltennamen normalerweise irrelevant, doch bei PostgreSQL stießen wir auf ein Problem bezüglich der ID-Spalte des Primärschlüssels in den Tabellen. Diese musste in Kleinbuchstaben als „id“ benannt werden. Dies sind typische Beispiele für unerwartete Portabilitätsprobleme;
Die drei Maven-Projekte zur Konfiguration der JPA-Schicht [2] eines bestimmten DBMS bestehen ebenfalls aus zwei Schritten:
- Importieren des JPA-Implementierungsarchivs;
- Konfigurieren der JPA-Implementierung, die für das spezifische verbundene DBMS verwendet wird. Tatsächlich ist es die JPA-Schicht, die SQL-Befehle an die JDBC-Schicht sendet. Um effektiv zu sein, muss sie das DBMS kennen, damit sie ihm SQL-Befehle senden kann, die es erkennt. Diese Befehle können sowohl das proprietäre SQL dieses DBMS als auch dessen spezifische Funktionen (Datentypen, Sequenzen, Trigger, Prozeduren, automatische Generierung von Primärschlüsseln usw.) nutzen;
Dies führt zu vierundzwanzig Maven-Konfigurationsprojekten (4 Konfigurationen × 6 DBMS), auf denen alle anderen Datenbankoperationsprojekte basieren werden. Da in den obigen Diagrammen die Schichten [DAO1] und [DAO2] dieselbe Schnittstelle bereitstellen, werden die 24 Konfigurationen der beiden oben genannten Architekturen mit einer einzigen Testklasse [JUnitTestsDao] getestet. Sobald diese Architekturen verifiziert sind, gibt es keine weiteren Schwierigkeiten:
- Das Maven-Projekt zur Veröffentlichung der Datenbank im Web basiert auf diesen beiden Architekturen. Daher gibt es auch hier 24 mögliche Konfigurationen;
- das Maven-Projekt zur Sicherung des Zugriffs auf den Webdienst baut auf dem vorherigen Projekt auf und verfügt ebenfalls über 24 mögliche Konfigurationen;
- Schließlich baut das Maven-Projekt, das domänenübergreifende Anfragen an den sicheren Webdienst ermöglicht, auf dem vorherigen Projekt auf und bietet ebenfalls 24 mögliche Konfigurationen;
Die Untersuchung wird unter Verwendung des DBMS MySQL5 und der JPA-Implementierung von Hibernate durchgeführt. Anschließend portieren wir den Code auf die JPA-Implementierungen von Eclipselink und OpenJPA. Schließlich portieren wir ihn auf andere Datenbanken (PostgreSQL, Oracle, SQL Server, DB2, Firebird).
Dieser Kurs richtet sich an Anfänger. Die meisten der verwendeten Konzepte werden erläutert. Vorkenntnisse in Datenbank- oder Webprogrammierung sind nicht erforderlich. Allerdings sind fundierte Kenntnisse der SQL-Sprache notwendig, da die verwendeten SQL-Abfragen nicht erklärt werden.
Um die Beispiele zu verstehen, benötigen Sie Grundkenntnisse der Java-Sprache, die in jedem Einführungskurs zu dieser Sprache vermittelt werden. Die ersten beiden Kapitel des Dokuments [Einführung in die Java-Sprache] reichen aus. Es handelt sich um ein älteres Dokument (1998, überarbeitet 2002), aber die Grundlagen sind darin enthalten. Für einen umfassenden Kurs empfiehlt sich das umfangreiche Buch von Jean-Marie Doudoux [http://www.jmdoudoux.fr/java].
Dieses Dokument erhebt keinen Anspruch auf Vollständigkeit. Es soll lediglich eine Methodik und Code bereitstellen, die in ähnlichen Kontexten wiederverwendet werden können. Das Dokument wurde so verfasst, dass es auch ohne Computer zur Hand gelesen werden kann. Daher sind viele Screenshots enthalten.
Obwohl es nicht alle Möglichkeiten der Java-Sprache oder alle ihre Anwendungsbereiche abdeckt, kann dieses Dokument als Lernressource für die Sprache genutzt werden. Wenn man diesem Dokument folgt – auch wenn nicht in seiner Gesamtheit –, wird ein Anfänger sowohl in der Verwendung der Sprache als auch im Spring-Framework ein „fortgeschrittenes Java“-Niveau erreichen. Anschließend kann man seine Java-Ausbildung mit den folgenden Büchern fortsetzen:
- [Spring MVC and Thymeleaf by Example] [https://stahe.github.io/en-springmvc-thymeleaf-janv-2015/], das die Erkundung des Spring-Ökosystems fortsetzt, indem es dessen Zweig „MVC-Webprogrammierung“ vorstellt;
- [AngularJS / Spring MVC Tutorial] [https://stahe.github.io/de-spring-angular1.x-juillet-2014/], das eine Client/Server-Webarchitektur vorstellt, bei der der Client mit dem [AngularJS]-Framework und der Server mit [Spring MVC] implementiert wird;
- [Einführung in Java EE], das sich vom Spring-Ökosystem wegbewegt hin zu einer Webarchitektur auf Basis von JSF (Java Server Faces) und EJB (Enterprise JavaBeans);
- [Einführung in die Android-Tablet-Programmierung] [https://stahe.github.io/de-android-aout-2016/], das eine Client/Server-Architektur beschreibt, bei der der Client ein Android-Tablet und der Server ein mit Spring MVC implementierter Webservice ist;
1.2. Quellen
Dieses Dokument stützt sich auf zwei Hauptquellen:
- [ ref1]: [Spring MVC und Thymeleaf anhand von Beispielen] unter der URL [https://stahe.github.io/de-springmvc-thymeleaf-janv-2015/]. Dieses Dokument greift die in [ref1] durchgeführten und vorgestellten Arbeiten unter Verwendung einer anderen Datenbank wieder auf. Einfach ausgedrückt: Es löst sie aus dem Kontext der Webprogrammierung mit Spring MVC heraus. Ich habe mich entschlossen, ein separates Dokument zu erstellen, da ich festgestellt habe, dass der in [ref1] verwendete Code und die Methodik zur Bereitstellung einer Datenbank im Web wiederverwendbar sind;
- [ ref2]: [Java Persistence in Practice] unter der URL [https://stahe.github.io/de-jpa-juin-2007/];
Um mehr über Spring zu erfahren, können Sie die folgenden Referenzen nutzen:
- das Referenzdokument zum Spring-Framework [http://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/spring-framework-reference.pdf];
- Zahlreiche Spring-Tutorials finden Sie unter der URL [http://spring.io/guides];
- die [developpez.com]-Website zum Thema Spring [http://spring.developpez.com/];
- das Tutorial [http://www.tutorialspoint.com/spring/spring_tutorial.pdf];
Leser mit unzureichenden SQL-Kenntnissen können die Grundlagen aus dem Buch [Einführung in SQL mit dem Firebird-DBMS] unter der URL [https://stahe.github.io/de-sql-firebird-janv-2006/] erlernen.
1.3. Verwendete Tools
Die folgenden Beispiele wurden in der folgenden Umgebung getestet:
- Windows 8.1 Pro 64-Bit-Rechner;
- JDK 1.8 (Abschnitt 23.1);
- Spring Tool Suite 3.6.3 IDE (Abschnitt 1);
- Chrome-Browser (andere Browser wurden nicht verwendet);
- Chrome-Erweiterung [Advanced Rest Client] (Abschnitt 1);
- MySQL 5.6 Community Edition DBMS (Abschnitt 23.4);
- SQL Server 2014 Express (Abschnitt 23.9);
- PostgreSQL 9.4 (Abschnitt 23.7);
- Oracle Express 11g Release 2 DBMS (Absatz 23.6);
- IBM DB2 Express-C 10.5 DBMS (Abschnitt 23.8);
- Firebird 2.5.4 DBMS (Abschnitt 23.10);
- die EMS-Manager-Clients für diese sechs DBMS (Abschnitt 23.5);
Hinweis zu JDK 1.8: Eine Methode in der Fallstudie verwendet eine Methode aus dem Paket [java.lang] in Java 8.
Die meisten Beispiele sind Maven-Projekte, die in Eclipse, IntelliJ IDEA oder NetBeans geöffnet werden können. Im Folgenden stammen die Screenshots aus der Spring Tool Suite IDE, einer Variante von Eclipse.
1.4. Die Beispiele
Die Beispiele stehen |HIER| als ZIP-Datei zum Download bereit.
![]() |
- In [1] befinden sich die Beispielordner;
- in [2] enthält der Ordner [spring-core] die Spring-Lernprojekte;
- in [3] enthält der Ordner [spring-database-config] die JDBC- und JPA-Konfigurationsprojekte für die sechs Datenbanken;
![]() |
- in [4] die Oracle-DBMS-Konfiguration. Sie enthält drei Ordner:
- [databases] enthält die SQL-Skripte zur Erstellung der beiden im Dokument verwendeten Datenbanken;
- [jdbc-driver] enthält den Oracle-JDBC-Treiber sowie ein Skript zu dessen Installation im lokalen Maven-Repository;
- [eclipse] enthält [5] die vier Oracle-Konfigurationsprojekte:
- [oracle-config-jdbc] konfiguriert die JDBC-Schicht für den Zugriff auf das DBMS;
- [oracle-config-jpa-hibernate] konfiguriert die JPA-Schicht für den Zugriff auf das DBMS unter Verwendung des Hibernate-JPA-Providers;
- [oracle-config-jpa-eclipselink] konfiguriert die JPA-Schicht für den Datenbankzugriff unter Verwendung des Eclipselink-JPA-Providers;
- [oracle-config-jpa-openjpa] konfiguriert die JPA-Schicht für den Datenbankzugriff unter Verwendung des OpenJPA-JPA-Providers;
- in [6] enthält der Ordner [eclipse config / launch configurations] die Startkonfigurationen, die der Leser in Eclipse importieren und dann an seine eigene Umgebung anpassen kann;
![]() |
- in [7] enthält der Ordner [spring-database-generic] den gesamten DB-Zugriffscode, der den sechs DBMS und den drei JPA-Anbietern gemeinsam ist;
- In [8] enthält [spring-jdbc] vier Projekte, die sowohl die JDBC-API als auch Spring JDBC demonstrieren;
- In [9] ist [spring-jpa / spring-jpa-generic] das Projekt, das eine JPA-Schicht für den Zugriff auf eine Datenbank verwendet. Die [generic-create-db*]-Projekte sind JPA-Projekte, die zum Anlegen der von der JPA-Schicht genutzten Datenbanken dienen;
![]() |
-
In [10] enthält der Ordner [spring-webjson] die Projekte, die die Datenbank im Web verfügbar machen;
- [spring-webjson-server-jdbc-generic] ist der Webdienst, der die über Spring JDBC zugängliche Datenbank bereitstellt;
- [spring-webjson-server-jpa-generic] ist der Webdienst, der die über Spring JPA zugängliche Datenbank bereitstellt;
- [spring-webjson-client-generic] ist der einzige Client, der den Zugriff auf die beiden vorgenannten Webdienste ermöglicht;
-
In [11] enthält der Ordner [spring-security] die Projekte, die die Datenbank im Web mit sicherem Zugriff bereitstellen;
- [spring-security-server-jdbc-generic] ist der sichere Webdienst, der die über Spring JDBC zugängliche Datenbank bereitstellt;
- [spring-security-server-jpa-generic] ist der sichere Webdienst, der die über Spring JPA zugängliche Datenbank bereitstellt;
- [spring-security-client-generic] ist der einzige Client, der den Zugriff auf die beiden zuvor genannten sicheren Webdienste ermöglicht;
-
In [12] enthält der Ordner [spring-cors] die Projekte, die die Datenbank im Web mit sicherem Zugriff bereitstellen und dabei domänenübergreifenden Zugriff ermöglichen, beispielsweise von JavaScript-Code eines Browsers aus;
- [spring-cors-server-jdbc-generic] ist der sichere Webdienst, der domänenübergreifenden Zugriff ermöglicht und die über Spring JDBC zugängliche Datenbank bereitstellt;
- [spring-cors-server-jpa-generic] ist der sichere Webdienst, der domänenübergreifenden Zugriff ermöglicht und die über Spring JPA zugängliche Datenbank bereitstellt;
- [spring-cors-client-generic] ist eine Webanwendung, die die beiden vorgenannten Webdienste abfragt;












