SQL-Tutorial Teil 2 - JDBC (Java Database Connectivity)
Teil 2 des SQL-Tutorials beschreibt die Verwendung der JDBC-API zum Erstellen eines Java-Clients für eine MySQL-Datenbank. Zunächst werden die grundlegenden JDBC-Funktionen an einem Mini-Beispiel "Datenabfrage mit JDBC" vorgestellt, das den Inhalt einer einzigen Tabelle abfragt. Abschließend folgt ein größeres Beispiel "Datenbank-Client mit JDBC", das einen Connection Pool für die effiziente Verwaltung offener Datenbankverbindungen verwendet. Zudem werden per Interface einheitliche Methoden zum Abfragen und Bearbeiten der Datenbanktabellen implementiert. Als Entwicklungsumgebung für den Java Client wird Visual Studio Code verwendet, und für die Projektverwaltung das Build-Management-Tool Maven. Als Vorbereitung sollte die Beispiel-Datenbank "University" CreateDatabaseUniversity(MySQL).sql mit dem hier verlinkten Skript in einer MySQL-Datenbank angelegt werden, wie im SQL-Tutorial beschrieben.
Motivation
Java ist für die Entwicklung von Datenbank-Clients besonders gut geeignet,
da sie eine objektorientierte Programmierung erzwingt, die gut auf die Tabellenstruktur relationaler Datenbanken abgebildet
werden kann.
Java Database Connectivity (JDBC) ist die zentrale Java-API, mittels deren Hilfe man in Java einen Datenbank-Client erstellt.
JDBC ist standardisiert, die aktuelle Version der JDBC-API ist 4.3.
Jeder Datenbank-Hersteller muss die Spezifikation der JDBC-API einhalten, dadurch wird der Zugriff auf verschiedene Datenbanken
unabhängig vom Hersteller ermöglicht.
Visual Studio Code wird aktuell vor allem für Python-Programmierung eingesetzt, verfügt jedoch über Extensions (Extension Pack for Java), die den Einstieg in die Java-Programmierung erleichtern. Wer in mehreren Sprachen programmiert und Visual Studio Code schon für Python- oder PHP-Programmierung einsetzt, kann direkt in Visual Studio Code auch Java programmieren.
Übersicht
Das Tutorial ist in vier Abschnitte gegliedert, die die JDBC-API, die Verwendung von JDBC-Treibern und die Erstellung eines Datenbank-Clients in Java mit JDBC beschreiben.
- 1 Datenbank-Clients entwickeln
- 2 JDBC-API: Übersicht
2-1 Datenbank mit JDBC abfragen
2-2 Connection Pool verwenden
2-3 Statement vs. Prepared Statement - 3 Datenbank-Treiber auswählen
3-1 JDBC-Treiber für SQL Server
3-2 JDBC-Treiber für MySQL - 4 Java-Programmierung mit Visual Studio Code und Maven
4-1 Visual Code für Java konfigurieren
4-2 Java Development Kit installieren
4-3 Java-Projekte mit Apache Maven verwalten - 5 Datenbank-Client mit JDBC und Connection Pool
5-1 Maven Projekt erstellen
5-2 Konfigurationsdatei pom.xml anpassen
5-3 Datenbanktabellen auf Klassen abbilden
5-4 Datenbankverbindung herstellen: Klasse DataSource
5-5 Datenbankzugriffe festlegen: Interface DataAccess
5-6 Datenbankzugriffe implementieren: StudentDataAccess
5-7 Datenbankzugriffe testen: UniversityClient
| Top |
1 Datenbank-Clients entwickeln
Datenbanken werden verwendet, um als Datenspeicher für Web- und Desktop-Anwendungen zu dienen.
Für den Datenbankzugriff aus einem Client bietet jede Programmiersprache spezielle API's an.
In Java:
JDBC-API: https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/
Die JDBC-API (Java Database Connectivity API) stellt eine standardisierte Funktionalität zur Verfügung und enthält lediglich Interfaces.
Die konkreten Implementierungen findet man in den JDBC-Treibern der verschiedenen DBMS-Anbieter.
In PHP:
MySQLi-Extension: https://www.php.net/manual/en/book.mysqli.php
Funktioniert nur mit MySQL, kein Datenbanktreiber erforderlich
PHP Data Objects (PDO): https://www.php.net/manual/en/intro.pdo.php
Funktioniert mit allen Datenbankservern, Datenbanktreiber erforderlich.
Java ist eine objektorientierte Programmiersprache, die vor allem für Desktop-Anwendungen in sicherheitskritischen Bereichen eingesetzt wird, z.B. im Bankenumfeld. Während bei Webanwendungen im Internet vor allem PHP- und JavaScript-basierte Frameworks zu finden sind, wird Java eher für unternehmensinterne Webanwendungen verwendet, bei denen die Daten in einer Datenbank erfasst werden und die eine Sitzungsverwaltung verwenden.
Die JDBC-API stellt Funktionalität zur Verfügung, mit der man in Java-Anwendungen die Verbindung zur Datenbank herstellen kann, SQL-Abfragen an den Datenbankserver sendet, die zurückerhaltenen Ergebnisse ausliest, und die Datenbankverbindung wieder schließt. Sie bildet weiterhin die Datentypen der Datenbanken auf Datentypen der Programmiersprache ab.
| Top |
2 JDBC API: Übersicht
JDBC (Java Database Connectivity) ist eine Java-Bibliothek, die eine einheitliche Schnittstelle zu relationalen Datenbanken verschiedener Hersteller bietet. Die JDBC API besteht aus den packages java.sql, javax.sql, die folgende Interfaces und Klassen enthalten:
- DriverManager: verwaltet JDBC-Treiber.
Wichtige Methoden: getConnection() - Connection: erstellt Verbindung mit einer Datenbank
Wichtige Methoden: createStatement(), prepareStatement(), close(), commit(), rollback() - Statement: Statische Datenabfrage
Wichtige Methoden: executeQuery(), executeUpdate() - PreparedStatement: Dynamische parametrisierte Datenbankabfrage
Wichtige Methoden: executeUpdate(), executeBatch() - ResultSet: kapselt das Ergebnis der Datenbankabfrage
Wichtige Methoden: first(), last(), next(), getInt(), getString(), updateRow(), close()
Das UML-Klassendiagramm zeigt einen Auszug der wichtigsten Klassen der JDBC-API mit den jeweiligen Abhängigkeiten. Es wird nur eine Auswahl der Methoden / Funktionen einer Klasse gezeigt, die vollständige Übersicht findet man in der Dokumentation der JDBC-API. Jede der Methoden kann im Fehlerfall eine SQLException auslösen, erkennbar an der Signatur der Methoden. Die vollständige Signatur der Methode getConnection() ist z.B.
Connection java.sql.DriverManager.getConnection(String url, String user, String password) throws SQLException
Dies bedeutet, dass die Methode in einen Try-Block eingebettet werden muss, damit der Fehler im Catch-Block angemessen abgefangen werden kann. Alternativ kann die SQLException mit einem throw an die aufrufende Funktion weitergereicht werden, die ihrerseits dann für die Fehlerbehandlung zuständig ist.
try {
Connection conn = DriverManager.getConnection(url, user, passwd);
}
catch (SQLException e){
// Hier Fehlerbehandlung, mindestens per Logging
}
| Top |
2-1 Datenbank mit JDBC abfragen
Der übliche Ablauf beim Abfragen einer Datenbank mit JDBC ist wie folgt.
Schritt 1 Verbindung aufbauen
Der Client baut eine Verbindung zum Datenbankserver (Datenbankmanagementsystem, DBMS) auf, den er anhand einer URL mit festgelegter Syntax identifiziert,
und authentifiziert sich mit dem Benutzernamen und Passwort eines Users, der zuvor im DBMS angelegt wurde.
Client und Server tauschen Meta-Informationen aus (Name des Protokolls, Version).
Schritt 2 Datenbankabfrage ausführen
Nach dem erfolgreichen Aufbau der Datenbankverbindung ("Connection") kann der Client SQL-Queries an den DBMS-Server senden.
Der Server führt die Query aus, und sendet die Ergebnisliste an den Client zurück.
Der Client prüft, ob die Ergebnisliste (ResultSet) nicht leer ist und liest die Zeilen in einer Schleife aus.
Schritt 3 Verbindung beenden
Die Verbindung muss nach Auführen der Datenabfrage geschlossen werden, da sonst unnötig Ressourcen belegt werden.
Beispiel: Datenbank mit JDBC abfragen
Die Methode testSelect() der Java-Klasse JDBCTest kapselt eine minimale Datenbankabfrage, die den Inhalt der Tabelle Student
der University-Datenbank als Liste speichert und ausgibt.
Das Java-Programm kann in Visual Studio Code ausgeführt werden, dafür muss zunächst ein Java-Projekt mit Maven angelegt werden,
wie in Abschnitt 5-1 Maven Projekt erstellen beschrieben, und die Java-Klasse dort angelegt werden.
JDBCTest.java
package com.hskl.dbs;import java.sql.*;import java.util.ArrayList;import java.util.List;record Student(String name, String vorname, int matrikelnr) {}public class JDBCTest {final static String url = "jdbc:mysql://localhost:3306/university";final static String driver = "com.mysql.cj.jdbc.Driver";final static String login = "<user>";final static String password = "<password>";public static void main(String[] args) {try {testSelect();} catch (SQLException e) {e.printStackTrace();}}public static void testSelect() throws SQLException {List<Student> stdList = new ArrayList<Student>();// (1) Datenbankverbindung herstellenConnection conn = DriverManager.getConnection(url, login, password);try { // (2) Datenbankabfrage ausführenString query = "SELECT Name, Vorname, Matrikelnr FROM Student";Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(query);if (rs != null) { // Solange es Datensätze gibtwhile (rs.next()) { // Schleife über die ErgebnislisteStudent st = new Student( rs.getString("name"),rs.getString("vorname"),rs.getInt("matrikelnr"));stdList.add(st);}}System.out.println(stdList.toString());}finally {conn.close(); // (3) Verbindung beenden}}}
Erläuterung
-
Der übliche Ablauf beim Abfragen einer Datenbank besteht im Herstellen der Datenbankverbindung, Ausführen der Datenabfrage und
Schließen der Datenbankverbindung. Bei jedem der Schritte können Fehler auftreten (falsche Datenbank-URL, fehlende Berechtigung,
Fehler in der SQL-Syntax). Die Fehler aus der Datenabfrage werden hier direkt in der Funktion testSelect() abgefangen, die Fehler aus dem
Herstellen und Schließen der Datenbankverbindung werden mit throws von der Funktion testSelect() an die aufrufende Funktion
weitergereicht.
- (1) Datenbankverbindung herstellen
Die Methode DriverManager.getConnection() benötigt als Parameter die URL der Datenbank sowie Login und Passwort des Datenbanknutzers.
Verwendete JDBC-Klassen: Connection, DriverManager - (2) Datenbankabfrage ausführen
Hier wird eine statische Datenbankabfrage ausgeführt. Zunächst wird die SQL-Query zusammengebaut, dann ein neues Statement erzeugt, dann die executeQuery-Methode des Statements aufgerufen und schließlich in einer Schleife die Datensätze ausgegeben.
Verwendete Klassen: Statement (Datenbankabfrage) und ResultSet (Ergebnisliste). - (3) Datenbankverbindung schließen
Das Schließen der Datenbankverbindung ist ein wesentlicher Schritt. Verbindungen, die offen bleiben, belegen auf dem Datenbankserver unnötig Ressourcen. Die Verbindung wird im finally-Teil eines try-finally-Blocks geschlossen.
Eine Datenbankverbindung sollten einerseits nach Durchführen der Abfragen geschlossen werden, da zu viele offene Verbindungen die Datenbank überlasten. Andererseits ist die Wiederverwendung offener Verbindungen wünschenswert, weil der Aufbau einer Datenbankverbindung-Verbindung eine zeitintensive Operation ist. Bei kleinen Desktop-Clients kann z.B. eine einmal geöffnete Datenbankverbindung für mehrere aufeinanderfolgende Abfragen verwendet werden und erst bei Schließen des Clients geschlossen werden. Web-Anwendungen mit vielen Abfragen, wo viele Clients gleichzeitig auf die Datenbank zugreifen, müssen für das Öffnen und Schließen von Datenbankverbindungen Connection Pools einsetzen, das sind Komponenten, die eine optimale Wiederverwendung der Datenbankverbindungen ermöglicht.
| Top |
2-2 Connection Pools
Das Aufbauen und Schließen einer Datenbankverbindung ist ein aufwendiger Schritt, der durch Connection Pooling verbessert werden kann. Ein Connection Pool ist ein Framework, das die Wiederverwendung physischer Datenbankverbindungen ermöglicht und die Geschwindigkeit des Datenbankzugriffs und den Speicherverbrauch optimiert. In einem Connection Pool wird eine festgelegte Anzahl Verbindungen offengehalten und diese werden wiederverwendet. In Java ist Connection Pooling entweder Teil des JDBC-Treibers, oder eine separate Klassenbibliothek (HikariCP), oder wird als Teil eines Application Servers (JBoss, Tomcat) angeboten. JDBC 2.0 definiert das Interface ConnectionPoolDataSource, das eine Schnittstelle für die Erzeugung von Pooled Connections zur Verfügung stellt.
| Top |
2-3 Abfragen per Statement oder Prepared Statement
Ein Prepared Statement ist eine dynamische parametrisierte Abfrage. Die Kommunikation mit dem Datenbankservern läuft in zwei Schritten ab: zunächst wird eine Datenabfrage mit Platzhaltern (z.B. ?) an den Server gesendet, danach nur noch die Werte, die an die Platzhalter gebunden werden.
Prepared Statements haben im Vergleich zu Statements zwei Vorteile, sie verbessern die Performance und Sicherheit der Datenbankabfrage.
Performance: Soll ein Statement mit unterschiedlichen Parametern wiederholt ausgeführt werden, sind Prepared Statements effizienter,
da das Statement schon vorübersetzt am Server vorliegt und nur noch mit den neuen Parametern ausgeführt werden muss.
Sicherheit: Mittels Prepared Statement können Angriffe wie SQL Injection verhindert werden, da das Datenbanksystem
die Gültigkeit von Parametern prüft, bevor diese verarbeitet werden.
3 Datenbanktreiber auswählen
| Top |
Ein Datenbanktreiber ist eine Java-Bibliothek bzw. ein Programm-Paket (*.jar-Datei), das die konkrete Implementierung der in der JDBC-API spezifizierten Schnittstellen für ein bestimmtes Datenbankmanagementsystem (DBMS) enthält. Jeder DBMS-Hersteller bietet Java-Datenbanktreiber für alle gängigen Programmiersprachen an. Datenbanktreiber können entweder auf der Webseite des Herstellers als *.jar-Datei heruntergeladen werden, oder automatisiert durch die Verwendung des Build-Tools Maven als Projektbibliothek eingetragen werden, dann übernimmt Maven den Download.
Bei der Wahl des passenden Treibers muss auf Kompatibilität geachtet werden: die Version des Treibers muss zur Version des installierten DBMS und zur verwendeten Java-Version passen. Informationen dazu findet man auf der JDBC-Webseite des jeweiligen Herstellers.
3-1 JDBC-Treiber für SQL Server: MSSQL JDBC
Der JDBC-Treiber für SQL Server heißt MSSQL JDBC und implementiert die Java Database Connectivity API für SQL Server. Microsoft bietet auf der Webseite des SQL Server aktuelle Versionen des JDBC-Treibers zum Download an, inklusive Anleitungen. Die JDBC-Treiber heißen mssql-jdbc-12.4.1.jre11.jar oder so ähnlich, wobei am Namen zu erkennen ist, zu welcher Java-Version sie jeweils passen.
3-2 JDBC-Treiber für MySQL: MySQL Connector-J
| Top |
Der offizielle JDBC-Datenbanktreiber für MySQL ist MySQL Connector/J und wird auf der Webseite des DBMS-Herstellers zum Download angeboten, inklusive Anleitungen zur Verwendung. Die JDBC-Treiber heißen mysql-connector-java-8.0.13.jar oder so ähnlich, wobei am Namen die Version des Treibers zu erkennen ist, und zu welcher Java-Version er jeweils passt.
Das Herunterladen der Jar-Datei in der passenden Version von der Webseite des Hersteller und Einbinden in den Java Bild-Path des Java-Projekts kann entweder manuell erfolgen, oder mit dem Projektverwaltungs-Tool Maven automatisiert werden. Bei der Verwendung von Maven werden die benötigten Java-Pakete in die zentrale Konfigurationsdatei pom.xml eingetragen und infolgedessen von Maven automatisch aus dem Maven Repository heruntergeladen.
4 Java-Programmierung mit Visual Studio Code und Maven
| Top |
Für die Entwicklung von Java-Programmen stehen Entwicklungsumgebungen wie IntelliJ IDEA und Eclipse zur Verfügung, die die benötigte Funktionalität für professionelle Software-Entwicklung mit Java einbinden. Für Einsteiger sind diese Entwicklungsumgebungen gerade wegen der Vielzahl an Funktionen oft zu mächtig, hier sind "leichte" Entwicklungsumgebungen wie Visual Studio Code nützlich.
4-1 Visual Code für Java konfigurieren
Visual Studio Code ist eine minimalistische Entwicklungsumgebung von Microsoft, die aktuell vor allem für Python-Programmierung eingesetzt wird. Visual Studio Code kann über verschiedene Extensions auch für Java-Programmierung eingesetzt werden.
Um Visual Studio Code für Java Programmierung zu verwenden, muss zunächst Microsoft's Extension Pack for Java installiert werden. Diese Extension enthält eine Reihe von Komponenten, die für die Java-Entwicklung wichtig sind: Language Support for Java™ by Red Hat, Debugger for Java, Test Runner for Java, Maven for Java, Project Manager for Java und Visual Studio IntelliCode.
Nach der Installation des Extension Packs für Java wird das Plugin unter den installierten Extensions angezeigt.
4-2 Java Development Kit installieren
| Top |
Für die Java-Programmierung wird ein aktuelles JDK (Java Development Kit) benötigt.
Das JDK besteht aus der Java Runtime (JRE) und enthält auch den Source Code der Java Standardpakete, was zum Debuggen benötigt wird.
Es stehen zwei JDKs zur Auswahl:
1. Oracle JDK
ist für die kommerzielle Verwendung lizenzpflichtig, kann für den persönlichen Gebrauch kostenlos verwendet werden.
Aktuellere JDK-Versionen sind 21, 22 und 23. Für die Durchführung des Tutorials wird
der Download der JDK-Version 21 als zip-Datei empfohlen, der Name ist jdk-21_windows-x64_bin.zip oder ähnlich.
2. OpenJDK
ist eine kostenlose Open Source-Version des Oracle JDKs und im wesentlichen identisch.
OpenJDK wird von unterschiedlichen Organisationen bereitgestellt, wie z.B. RedHat oder Adoptium.
Adoptium ist eine Community-Organisation, die kostenlose Java-Laufzeitumgebungen (JDK/JRE) zur Verfügung stellt.
Aktuellere OpenJDK-Versionen sind 21 und 25. Für die Durchführung des Tutorials wird der Download der OpenJDK-Version 21 als zip-Datei empfohlen, der Name ist OpenJDK21U-jdk_x64_windows_hotspot_21.0.9_10.zip oder ähnlich.
Nach dem Herunterladen und Extrahieren der Datei in einen passenden Ordner z.B. C:\Java\OpenJDK21U\jdk-21.0.9+10, sollte die System-Umgebungsvariable JAVA_HOME auf den Ordner gesetzt werden, dies erfolgt über Systemeinstellungen > "Systemumgebungsvariablen bearbeiten". Weiterhin sollte der Ordner C:\Java\OpenJDK21U\jdk-21.0.9+10\bin der Systemumgebungsvariablen PATH hinzugefügt werden, also dem Systempfad, damit die Java Programme gefunden werden.
Das Setzen der Umgebungsvariablen wird überprüft, indem man im Terminalfenster (cmd) folgende Befehle eingibt:
4-3 Java-Projekte mit Apache Maven verwalten
| Top |
Apache Maven ist ein Build- und Projektverwaltungs-Tool, das für die automatisierte Entwicklung von Java-Projekten verwendet wird und den kompletten Lebenszyklus der Softwareentwicklung unterstützt: Installation, Kompilieren, Testen und Deployen von Java-Anwendungen. Maven kann auf zwei Arten verwendet werden: über Terminal-Kommandos wie mvn install, oder über die Menüpunkte einer Entwicklungsumgebung, in die Maven integriert ist. Einige Java-Entwicklungsumgebungen wie IntelliJ IDEA oder Eclipse haben Maven schon integriert. Bei Visual Studio Code wird Maven durch eine Extension eingebunden. Nach Installation der Extension hat man verschiedene Menüpunkte, um Maven-Projekte mit standardisierter Struktur zu erstellen und Maven Goals (install, compile, run) auszuführen. Ein Java-Projekt, das mit Maven erstellt wird, hat eine standardisierte Projekt-Struktur und eine zentrale Konfigurationsdatei pom.xml, in die alle Informationen zum Ausführen des Projektes eingetragen werden.
Man kann Projekte aus den Vorlagen des Maven Repository erstellen. Die Projektabhängigkeiten werden über eine Konfigurationsdatei pom.xml konfiguriert. Damit entfällt das Herunterladen und manuelle Einhängen der *.jar-Dateien im Projekt. Maven ist verfügbar in allen Java-IDEs: Eclipse, IntellijIdea, Visual Studio Code.
5 Datenbank-Client mit JDBC und Connection Pool
In diesem Beispiel wird ein Java-Client mittels JDBC erstellt, und zwar für eine University-Datenbank, die Studiengänge, Studenten
und Module verwaltet, und auch im
SQL-Tutorial auf dieser Webseite verwendet wird.
Als Vorbereitung sollte man MySQL via XAMPP installieren und die Beispiel-Datenbank "University" per hier verlinktem Skript erstellen.
CreateDatabaseUniversity(MySQL).sql
Der Java-Client für die University-Datenbank wird jede Datenbanktabelle mit einer entsprechenden Java-Klasse abbbilden, d.h. zur Tabelle Student gibt es eine Klasse Student mit denselben Attributen, und für jede Tabelle Methoden anbieten, mit denen man Datensätze einfügen, ändern, löschen und abfragen kann. Die Methoden für die Datenbankzugriffe werden in einer Java-Schnittstelle ("Interface") festgelegt, wir nennen sie: insert(), update(), delete() und findAll().
UML-Klassendiagramm
Erläuterung des Diagramms
Das UML-Klassendiagramm beschreibt den Aufbau des Packages com.hskl.university.dataaccess, das die Klassen für den Java-Client mit JDBC enthält.
- DataSource - Klasse, dient dem Herstellen einer Datenbankverbindung
- DataAccess - Interface, legt die Methoden für die Datenbankzugriffe fest
- StudentDataAccess - Subklasse von DataSource, implementiert das Interface DataAccess
- Student - bildet die Datenbanktabelle Student als Klasse ab
5-1 Java-Projekt mit Maven erstellen
| Top |
Die Erstellung eines neuen Java-Projektes mit Maven ist in der folgenden Slideshow beschrieben, die auszuwählenden Eingaben sind farblich hervorgehoben. Hier wird ein einfaches Maven-Projekt ohne Vorlage erstellt ("no archetype"), dabei ist zunächst nur die Projektstruktur und eine minimale Konfigurationsdatei pom.xml ohne Abhängigkeiten vorhanden.
- Schritt 1: File > New > New Java Project ... (Project Manager for Java)
- Schritt 2: Maven create from archetype (provided by Maven for Java)
- Schritt 3: No archetype (create a basic Maven project directly)
- Schritt 4: New Maven Project: Input group ID of your project: com.hskl.university.dataaccess
- Schritt 5: New Maven Project: Input artifact ID (also project name): universityclient
- Schritt 6: Auswählen eines Ordners im Dateisystem als Projektablage. Hier wird der zuvor erstellte Ordner Workspace ausgewählt. Das Projekt universityclient wird dann als Unterordner des Ordners Workspace abgelegt.
- Schritt 7: Es erscheint eine Meldung, die die Erstellung des Projekts universityclient im Ordner Workspace bestätigt.
| Top |
5-2 Konfigurationsdatei pom.xml anpassen
Das im vorigen Schritt erstellte Java-Projekt mit Maven wird für die Verwendung der JDBC-Treiber konfiguriert. Dafür werden in der Maven-Konfigurationsdatei pom.xml die benötigten Java-Bibliotheken als Abhängigkeiten ("dependencies") eingetragen. Für einen Datenbank-Client werden mindestens zwei Dependencies benötig: zunächst der JDBC-Treiber selber und zusätzlich eine Connection Pool-Implementierung, die die offenen Datenbankverbindungen verwaltet.
Die korrekten Angaben für einen Datenbanktreiber entnimmt man dem Maven Repository, https://mvnrepository.com/.
Das Maven Repository ist eine Online-Plattform, in der die Hersteller von Java-Paketen zentral die Angaben hinterlegen,
die ein Java-Programmierer benötigt, um das jeweilige Paket in der eigenen Anwendung verwenden zu können.
Man findet die Dependency-Einträge von Java-Bibliotheken im Maven Repository entweder über die Menüleiste,
die verschiedene Kategorien zusammenfasst z.B. Logging Frameworks, Testing Frameworks oder JDBC Drivers) oder über die Suche.
Konfigurationsdatei pom.xml
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.hskl.university</groupId><artifactId>universityclient</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target></properties><dependencies><!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>9.1.0</version></dependency><!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP --><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId><version>7.0.2</version></dependency></dependencies></project>
Maven Repository
https://mvnrepository.com/artifact/com.mysql/mysql-connector-j
| Top |
5-3 Datenbanktabellen auf Klassen abbilden
Jede Datenbanktabelle wird durch eine POJO (plain old java object)-Klasse abgebildet, die lediglich die Attribute / Spalten der Tabelle, einen Klassen-Kostruktor,
öffentliche Getter-und Setter-Methoden für die Attribute, und eine toString-Methode enthält.
Die Tabelle Studiengang wird durch die Klasse Studiengang abgebildet, mit den Attributen ID, name und art.
Die Tabelle Student wird durch eine Klasse Student abgebildet, mit den Attributen ID, name, vorname, matrikelnr, semester und studiengang.
POJO-Klasse Studiengang
package com.hskl.university.dataaccess;public class Studiengang {int ID = 1;String name = "";String art = "";public Studiengang(int ID){this.ID = ID;}public Studiengang(int iD, String name, String art) {this.ID = iD; this.name = name; this.art = art;}public int getID() {return ID;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getArt() {return art;}public void setArt(String art) {this.art = art;}@Overridepublic String toString() {return "Studiengang [name=" + name + ", art=" + art + "]\n";}}
POJO-Klasse Student
package com.hskl.university.dataaccess;public class Student {int ID = 0;String name;String vorname;int matrikelnr = 0;int semester = 0;Studiengang studiengang = new Studiengang(1, "", "");public Student(String name, String vorname, int matrikelnr) {this.name = name;this.vorname = vorname;this.matrikelnr = matrikelnr;}public String getName() {return name;}public void setName(String name) {this.name = name;}// Weitere Getter und Setter@Overridepublic String toString() {return String.format(" %10s %10s %10d\n",this.name, this.vorname, this.matrikelnr);}}
Mit Hilfe der POJO-Klassen kann man neue Studiengang- und Student-Instanzen erstellen, wie in dem folgenden Beispiel.
Studiengänge und Studenten erstellen
Studiengang stg = new Studiengang(1, "Elektrotechnik", "Master");Student anna = new Student("Test", "Anna", 11222);anna.setStudiengang(stg);System.out.println(anna.toString());
| Top |
5-4 Datenbankverbindung herstellen: Klasse DataSource
Die Klasse DataSource dient dem Erstellen einer Verbindung zur Datenbank. Hier werden die Verbindungsdaten festgelegt: URL, Benutzername und Passwort, und es wird eine statische Instanz des HikariCP ConnectionPools erstellt.
Klasse DataSource
package com.hskl.university.dataaccess;import java.sql.Connection;import java.sql.SQLException;import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;public class DataSource {private final static String url = "jdbc:mysql://localhost:3306/university";private final static String login ="student01";private final static String password = "dbs";private static HikariDataSource ds = null;static {HikariConfig config = new HikariConfig();config.setJdbcUrl(url);config.setUsername(login);config.setPassword(password);config.addDataSourceProperty("minimumIdle", "5");config.addDataSourceProperty("maximumPoolSize", "25");ds = new HikariDataSource(config);}public static Connection getConnection() throws SQLException {return ds.getConnection();}public static void closeConnection() throws SQLException {ds.getConnection().close();}}
Klasse DataSource testen
package com.hskl.university.dataaccess;import java.sql.Connection;import org.junit.Test;public class DataSourceTest {@Testpublic void testGetConnection() throws Exception {Connection conn = DataSource.getConnection();try {System.out.println("Datenbankverbindung offen!");System.out.println("Datenbanksystem: "+ conn.getMetaData().getDatabaseProductName());}finally {conn.close();System.out.println("Datenbankverbindung geschlossen!");}}}
5-5 Datenbankzugriffe festlegen: Interface DataAccess
| Top |
Das Interface DataAccess legt die zulässigen Datenbankzugriffe fest, also welche Methoden zum Einfügen, Ändern, Löschen und Auslesen der Datenbanktabellen im Client benötigt werden. Anschließend wird für jede Datenbanktabelle eine Realisierungs-Klasse für das Interface geschrieben, die die konkrete Implementierung der festgelegten Methoden enthält.
Interface DataAccess
package com.hskl.university.dataaccess;import java.util.List;public interface IDataAccess<T> {int insert(T obj) throws SQLException;int update(T obj) throws SQLException;int delete(T obj) throws SQLException;void insertAll(List<T> list) throws SQLException;List<T> findAll() throws SQLException;List<T> find(T filter) throws SQLException;}
| Top |
5-6 Datenbankzugriffe implementieren: StudentDataAccess
Die Klasse StudentDataAccess implementiert die im Interface IDataAccess festgelegten Methoden: insert, update, delete, findAll, insertAll, - sowie alle weiteren Methoden, die die Anwendung benötigen könnte. Hier werden beispielhaft einige der Methoden umgesetzt.
1 insert: Studenten einfügen
Die Methode insert() fügt einen Studenten ein und gibt 1 zurück, wenn der Student eingefügt werden konnte,
und ansonsten 0.
2 findAll: Alle Studenten ausgeben
Die Methode findAll() gibt eine Liste aller Studenten zurück, wobei für jeden Studenten auch
der Studiengang mit abgefragt wird.
package com.hskl.university.dataaccess;import java.sql.*;import java.util.ArrayList;import java.util.List;public class StudentDataAccess implements DataAccess<Student>{@Overridepublic int insert(Student st) throws SQLException {Connection conn = DataSource.getConnection();try {String sql = "INSERT INTO Student(Name, Vorname, Matrikelnr, StudiengangID) VALUES (?, ?, ?, ?)";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1, st.getName());ps.setString(2, st.getVorname());ps.setInt(3, st.getMatrikelnr()); ps.setInt(4, st.getStudiengang().getID());int rowcount = ps.executeUpdate();return rowcount;} finally {conn.close();}}@Overridepublic List<Student> findAll() throws SQLException {// TODO: Code aus der Slideshow einfügen}}
Weitere Funktionen für den Datenbankzugriff
Eine Auswahl der Methoden / Funktionen, die den Datenbankzugriff in der Klasse StudentDataAccess umsetzen, sind in der Slideshow einsehbar:
insert() - einen Studenten einfügen, insertAll() - eine Liste von Studenten einfügen,
findAll() - alle Zeilen der Tabelle Student auslesen
deleteAll(int lastid) - alle Studenten löschen, deren ID größer ist als lastid.
Einige der Methoden verwenden statische Abfragen (Statement), andere dynamische parametrisierte Abfragen (PreparedStatement).
| Top |
5-7 Datenbankzugriffe testen: UniversityClient
Die Klasse UniversityClient ist die Testklasse des Java-Projektes und enthält mit der main-Methode den Einstiegspunkt des Projektes. Der abgebildete Test-Ablauf ist wie folgt: Zunächst wird eine Instanz der Klasse StudentDataAccess angelegt, dadurch haben wir Zugriff auf die im Interface DataAccess festgelegten Methoden: insert, update, delete und findAll. Danach wird erst der Inhalt der Tabelle Student ausgegeben, dann ein neuer Student eingefügt, und dann der Inhalt der Tabelle noch einmal ausgegeben.
Quellcode UniversityClient.java
package com.hskl.university.dataaccess;import java.util.ArrayList;import java.util.List;public class UniversityClient {public static void main(String[] args) {DataAccess<Student> stda = new StudentDataAccess();try {List<Student>students = stda.findAll();System.out.printf("Vorher: %d Studenten\n", students.size());int deleted = stda.deleteAll(10);System.out.println("Gelöscht " + deleted + " Studenten ");int inserted = stda.insert(new Student("Test", "Anna", 11222));System.out.println("Eingefügt " + inserted + " Studenten ");students = stda.findAll();System.out.printf("Nachher: %d Studenten\n", students.size());System.out.println(students.toString());} catch (Exception e) {e.printStackTrace();}}}
Ausgabe
Nächste Schritte
Das Tutorial zeigt den Einsatz von JDBC in kleineren prototypischen Anwendungen. Größere Anwendungen, die ihre Daten aus einer Datenbank beziehen, verwenden meist eine Daten-Persistenzschicht, um die Datenobjekte im Arbeitsspeicher vorzuhalten. Die wichtigste Aufgabe der Daten-Persistenzschicht ist das Objekt-Relationale Mapping (ORM), bei dem das objektorientierte Datenmodell der Anwendung auf das relationale Datenmodell der Datenbank abgebildet wird. Die meisten Programmiersprachen bieten ein ORM-Framework an. In Java verwendet man die Java Persistence API (JPA) und Hibernate, in PHP: Doctrine und in Python: SQLAlchemy.
Tools, Quellen und weiterführende Links
Tools:
- [1] SQL Server Developer oder Express: microsoft.com/de-de/sql-server/sql-server-downloads
- [2] JDBC Spezifikation: jdbc4.3-fr-spec.pdf
- [3] MySQL: mysql.com
- [4] XAMPP: apachefriends.org
Quellen und weiterführende Links:
- [1] MySQL SQL-Referenz: dev.mysql.com/doc/refman/8.0/en/sql-statements.html
- [2] SQL-Tutorial: https://www.evamariakiss.de/tutorial/sql/
- [3] Erste Schritte mit phpMyAdmin: https://www.evamariakiss.de/tutorial/phpmyadmin/