Falconbyte unterstüzen
Betrieb und Pflege von Falconbyte brauchen viel Zeit und Geld. Um dir auch weiterhin hochwertigen Content anbieten zu können, kannst du uns sehr gerne mit einem kleinen "Trinkgeld" unterstützen.
Schnelles Code-Beispiel:
//Treiber laden und verbinden
Class.forName("org.h2.Driver");
Connection con = DriverManager.getConnection("jdbc:h2:file:~/data/test", "user","");
Was ist eine eingebettete Datenbank?
Eine eingebettete Datenbank ist eine Datenbank, die ohne Server funktioniert. Sie ist vollständig in der Anwendungssoftware eingebettet und tritt nach außen nicht in Erscheinung. Ein Zugriff auf die eingebettete Datenbank ist deshalb von außerhalb erst einmal nicht möglich.
In unseren Kapiteln zu Java und MySQL hatten wir es mit externen Datenbanken zu tun. Diese liefen unabhängig von unserem Java-Programm standalone.
Die Infografik unten zeigt den prinzipiellen Unterschied zwischen einer eingebetteten Datenbank und einer externen Datenbank:
- Eine eingebettete Datenbank ist serverlos. Es kann immer nur eine Verbindung zur Datenbank bestehen. Multiple Verbindungen sind ohne Weiteres nicht möglich.
Es gibt unterschiedliche Datenbanksysteme, die direkt in unserer Java-Programm eingebettet werden können. Zum Beispiel:
Wir entscheiden uns in diesem Tutorial für die H2 Datenbank. Sie ist besonders flott einzurichten und hat noch folgende Vorteile:
- Sehr schnell
- Minimaler footprint (nur ca. 2MB für die jar-Datei)
- Unterstützt Standard-SQL und die Java JDBC API
- Kann neben dem eingebetteten Modus (Standard) auch im Server-Modus arbeiten
- Datenspeicherung in-memory oder datei-basiert
Also, los gehts 🤠
H2 Datenbank installieren
Die Installation der H2 Datenbank in unserem Java-Projekt ist sehr einfach.
jar-Datei besorgen
Lade dir zunächst die jar-Datei für das H2 Datenbanksystem herunter. Auf der offiziellen Seite von H2 kannst du dir im Download-Bereich eine Platform-Independent Zip der neuesten Version runterladen. In dieser zip-Datei befindet sich im bin-Ordner die jar-Datei (z.B. h2-1.4.200.jar) - und genau diese eine Bibliotheks-Datei brauchen wir.
Als nächsten bindest du die jar in dein Java-Projekt ein:
- IntelliJ: Klicke in der Seitenleiste links ein Java-Projekt an. Gehe anschließend im Programm-Menu auf file > project structure... > libraries. Klicke im Project Structure-Menu auf das + Zeichen und füge jetzt die externe Klassenbibliothek dem Projekt hinzu, indem du die jar-Datei auswählst.
- Eclipse: Wähle in der Seitenleiste links ein Java-Projekt aus. Gehe im Programm-Menu oben auf File > Properties. Es erscheint das Menu für die Properties. Wähle darin Java Build Path > Libraries > Add External JARs... und füge die jar-Datei hinzu.
Treiber laden
Die Kommunikation mit der H2 Datenbank erfolgt mittels der JDBC. Hierzu müssen wir zuerst den JDBC Datenbanktreiber für das H2 System laden:
Class.forName("org.h2.Driver");
Zur Datenbank verbinden
Die Verbindung zur Datenbank wird durch die Connection-Instanz repräsentiert. Wir erhalten diese, indem wir die statischen getConnection()-Methode aufrufen.
Connection con = DriverManager.getConnection("jdbc:h2:file:~/data/test", "user","");
getConnection hat drei String-Parameter: Die JDBC-Url, den Datenbanknutzer ("user") und ein Datenbankpasswort (leer).
Die JDBC-URL ist in unserem Beispiel jdbc:h2:file:~/data/test. Bei Unix/ Linux basierten Betriebssystemen bedeutet das, dass die eingebettete Datenbank namens test im Home Verzeichnis des Nutzers im Ordner data lokal gespeichert wird.
In Windows müsste die JDBC-URL so aussehen: jdbc:h2:file:C:/data/test.
Statements ausführen
Wir können unserer H2 Datenbank vollständig mit Standard-SQL verwalten. Die uns bekannten JDBC-Klassen und -Interfaces machen die Kommunikation zwischen Java und der Datenbank möglich.
Mit folgendem Code verbinden wir zur H2 Datenbank, erstellen eine Tabelle, fügen einen Datensatz ein und lesen ihn dann einmal aus:
package p1;
import java.sql.*;
public class DBTest {
public static void main(String[] args){
try {
//Treiber laden und verbinden
Class.forName("org.h2.Driver");
Connection con = DriverManager.getConnection("jdbc:h2:file:~/data/test", "user","");
// Statement Objekt erstellen
Statement stm = con.createStatement();
// Tabelle erstellen
String sql_create = "CREATE TABLE IF NOT EXISTS kunden(id INTEGER, name VARCHAR(50), vip BOOLEAN);";
stm.execute(sql_create);
// Datensatz einfügen
String sql_insert = "INSERT INTO kunden(id, name, vip) VALUES(1, 'Elon Musk', TRUE)";
stm.execute(sql_insert);
// Datensatz auslesen
String sql_select = "SELECT * FROM kunden";
ResultSet rs = stm.executeQuery(sql_select);
while(rs.next()){
System.out.println(rs.getString(1) + " " +
rs.getString(2) + " " +
rs.getString(3));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Altenative Verbindungsarten
Das H2 Datenbanksystem ist sehr flexibel und ermöglicht mehrere unterschiedliche Verbindungsmodi. Diese werden einfach über eine Anpassung der Datenbank-URL eingestellt. Im Folgenden schauen wir uns zwei unterschiedliche Modi genauer an:
- in-memory Modus
- Mixed-Modus
Eine vollständige Liste aller Verbindungsarten kannst du auf der offiziellen Website von H2 nachlesen.
in-memory Datenbank
Im bisherigen Beispiel wurde unsere Datenbank lokal in einer Datei gespeichert. Die Daten sind damit persistent, d.h. dauerhaft verfügbar.
Es ist aber nicht immer ideal, Datenbanken persistent zu halten. In einigen Fällen empfielt es sich nämlich, sie stattdessen in den Arbeitsspeicher zu laden. Solche Datenbanken werden in-memory Datenbanken genannt.
Was sind die Vorteile? Das Laden in den Arbeitsspeicher ermöglicht deutlich höhere Zugriffsgeschwindigkeiten und bessere Performance. Allerdings werden die Daten beim Schließen des Programms gelöscht. Hier einige Beispiele, wo in-memory Datenbanken zum Einsatz kommen:
- High Performance Operationen
- Schnelles Prototyping
- Read-only Datenbanken
Das H2 Datenbanksystem unterstützt einen in-memory-Modus für solche Zwecke. Eine in-memory Datenbank kann über folgende Modus-Anpassung in der JBDC-URL erstellt werden: jdbc:h2:mem:datenbank_name
Hier ein Beispiel:
DriverManager.getConnection("jdbc:h2:mem:test2", "user",""); // in-memory-Datenbank
Die "temporäre" Datenbank namens test2 hat eine Lebensdauer, die der Laufzeit des Programms entspricht. Sie endet also mit dem Ende des Programms.
Multiple Zugiffe auf Datenbank ermöglichen
Im eingebetteten ("=serverlosen") Modus kann immer nur ein einziger Zugriff auf die Datenbank erfolgen. Häufig muss ein Zugriff auf eine Datenbank aber von mehreren Personen aus einem Netzwerk oder von verschiedenen virtuellen Maschinen erfolgen. Praktischerweise gibt es einen sog. Mixed Mode, der uns einen H2-Server starten lässt (und das ganz automatisch).
Der Mixed Mode ist eine Kombination aus dem eingebetteten Modus und einem Server-Modus. Das erste Programm startet die Datenbank im eingebetteten Modus, eröffnet gleichzeitig aber auch einen Server, mit dessen Hilfe andere Anwendungen auf die Datenbank zugreifen können. Die multiple Nutzung ein und derselben Datenbank wird möglich.
Am einfachsten erreichen wir das, indem wir ;AUTO_SERVER=TRUE an die Datenbank-URL anhängen:
// Application 1:
DriverManager.getConnection("jdbc:h2:file:~/data/test;AUTO_SERVER=TRUE");
// Application 2:
DriverManager.getConnection("jdbc:h2:file:~/data/test;AUTO_SERVER=TRUE");
Beim Einsatz dieser Verbindung nutzt der Server standardmäßig irgendeinen freien TCP Port. Der Port kann aber auch manuell umgestellt werden, z.B. AUTO_SERVER_PORT=9090.
Übungen
einfach
Was ist eine "eingebettete Datenbank"?
mittel
Wann ist der Einsatz des in-memory Modus sinnvoll?
schwer
Du hast foldenden Datenbank-Code in deinem Java-Programm unter Windows:
Class.forName("org.h2.Driver");
Connection con = DriverManager.getConnection("jdbc:h2:file:C:/data/db", "Armstrong","");
Du möchtest anderen Nutzern eines Netzwerks den Zugriff auf die Datenbank db ermöglichen. Wie muss der Code angepasst werden?