Datenbanken und Java in der Schule

In der 11. Jahrgangsstufe sollen die Schüler am bayerischen G8 ein Programmierprojekt in einer objektorientierten Sprache (in der Regel: Java) umsetzen, das mit einer SQL-Datenbank zusammenarbeitet. Die ISB-Handreichung stellt als Beispiel eine Börsensimulation und einen Fahrradroutenplaner zur Verfügung; ich habe schon mal mit Schülern zwei schöne Projekte gemacht und bin mit zwei anderen gescheitert. Dabei spielt die Datenbank für mich keine große Rolle; sie hat absolut nichts mit dem Lehrplan von Q11 oder Q12 zu tun, die Schüler interessieren sich nicht dafür, und für die meisten Projekte braucht man eigentlich keine. Das bisschen, das man meist speichern will, geht auch anders. Aber gut, es soll nun mal so sein.

Java und SQL-Datenbanken in der Schule haben einige Tücken, wie ich nach und nach herausgefunden habe. Mit etwas Basteln funktionierte das Projekt – zumindest in der Schule, aber nicht unbedingt bei den Schülern zu Hause, und nicht unter einem anderen Betriebssysteme, oder auch nur innerhalb der Entwicklungsumgebung und nicht als eigenstäniges Java-Produkt. Ich schreibe hier mal zusammen, was ich herausgefunden habe.

  1. Wahl des Datenbanksystems: Access, MySQL, SQLite, Base?
  2. Integrieren des passenden Treibers
  3. Grundsätzliche Aufbau einer Anfrage: Unterschiede bei der Syntax
  4. Die Verbindung zur Datenbank: Hauptproblem Speicherort bei lokalen Dateien

1. Wahl des Datenbanksystems

Es gibt viele Möglichkeiten, mit SQL-Syntax zu arbeiten.

MS Access

Vorteile: Treiber ist bereits vorhanden. Man kann die Datenbank leicht außerhalb von Java bearbeiten.
Nachteile: Läuft nur unter Windows und nur, wenn Access installiert ist.

MySQL-Server

Vorteile: Läuft bei allen Betriebssystemen. Man hat keine Probleme mit dem Speicherort der DB (siehe später).
Nachteile: Man muss den richtigen Treiber finden; man braucht schülerferne Werkzeuge wie phpMyAdmin, um die DB zu bearbeiten; und vor allem: man braucht einen laufenden MySQL-Server. Das geht in der Schule noch, aber zu Hause bei den Schülern schon weniger, und weitergeben an Eltern und Freunde kann man das Programm dann auch nur, wenn man denen die Serverinfrastruktur mitgibt.

Open Office Base

Vorteile: Läuft bei allen Betriebssystemen. Man kann die DB leicht in Base erstellen.
Nachteile: Man muss den richtigen Treiber finden. Vor allem: Java kann nicht unmittelbar mit der .odb-Datei arbeiten. Die ist eigentlich ein gezipptes Paket, das einen Ordner database enthält. Dieser Ordner enthält die 4 Dateien backup, data, properties und script. Die muss man auspacken und umbenennen in zum Beispiel xxx.backup, xxx.data, xxx.properties und xxx.script – und dann erst kann Java mit der Datenbank unter dem Namen xxx im HSQLDB-Format arbeiten.

SQLite

Vorteile: Läuft bei allen Betriebssystemen.
Nachteile: Man muss den richtigen Treiber finden. Es bietet nur eine – für die Schule aber voll ausreichende – Teilmenge von SQL; es gibt keine Fremdschlüssel und keine Kontrolle der Typen – um die Datenintegrität muss man sich selber kümmern. Zum Erstellen und Warten der DB braucht man ein eigenes Programm, davon gibt es aber genug, etwa den SQLite Database Browser.

— Inzwischen neige ich zu SQLite.

2. Integrieren des Treibers

Wenn man sich für ein DBS entschieden hat, braucht Java den Treiber dazu. Den findet man im Web in Form einer .jar-Datei, die man in sein Projekt integrieren muss. (Dafür gibt es verschiedene Möglichkeiten. In BlueJ bindet man die Datei als Bibliothek ein, oder man kopiert sie in einen Ordner namens +libs im BlueJ-Projektverzeichnis.)

DB-Typ Treiberbezeichner Präfix Treiber zu finden z.B. in
MS Access „sun.jdbc.odbc.JdbcOdbcDriver“ „jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=“ -integriert-
MySQL „com.mysql.jdbc.Driver“ „jdbc:mysql://“ mysql-connector-java-5.1.25-bin.jar
Base „org.hsqldb.jdbcDriver“ „jdbc:hsqldb:“ hsqldb.jar
SQLite „org.sqlite.JDBC“ „jdbc:sqlite:“ sqlite-jdbc-3.7.2.jar

Neben dem Treiber selber brauchte man in früheren Java-Versionen dessen Bezeichner, und man braucht immer noch einen Präfix dazu, der beim Einbauen dem Namen der DB vorangestellt wird.

3. Grundsätzliche Aufbau einer Anfrage

Ich habe den Aufbau einer SQL-Anfrag ein Java in 10 Schritte aufgeteilt. Hier sind sie in einer Klasse dazu. Damit das funktioniert, braucht man noch die Datenbankdatei quiz.sqlite, aber dazu später mehr.

import java.sql.*;
 
class DBVerbindung {
    //Attribute
    String treiberbezeichner = "org.sqlite.JDBC";
    String praefix = "jdbc:sqlite:";
    String urlstring = "quiz.sqlite";
    String user = "";
    String kennwort = "";
 
    //Anfragestring zu Demo-Zwecken hier ausgelagert
    String anfragestring = "SELECT * FROM fragen WHERE antwort1='H2O';";
    String spaltenbezeichner = "frage";
 
    void test() {
        try {
            //1. Treiber laden
            Class.forName(treiberbezeichner);
 
            //2. Verbindung herstellen
            Connection conn = DriverManager.getConnection(praefix+urlstring, user, kennwort);
 
            //3. Statement erzeugen
            Statement stmt = conn.createStatement();
 
            //4. Abfrage durchfuehren und Ergebnismenge erhalten
            ResultSet rset = stmt.executeQuery(anfragestring);
            //bzw. stmt.executeUpdat(auftragInSQL)
 
            //5. Ergebnismenge verarbeiten (in Schleife, mit getInt/getString)
            while (rset.next()) { System.out.println (rset.getString(spaltenbezeichner)); }
 
            //6. Ergebnismenge schliessen
            rset.close();
 
            //7. Statement schliessen
            stmt.close();
 
            //8. Verbindung schliessen
            conn.close();
        }
        catch (Exception e) {
            System.out.println(e);
        }
    }
}

Den Schritt 1 kann man in neueren Java-Versionen weglassen, da Java den Treiber automatisch lädt, wenn er den Präfix korrekt zuordnen kann. Schritt 2, der Aufbau der Verbindung zur Datenbank, macht am meisten Schwierigkeiten, dazu später. Schritt 4 und 5 sind das Stellen und Verarbeiten der SQL-Abfrage. Hier kann man natürlich optimieren, wenn man sich für geschickte SQL-Abfragen interessiert. Für ein Schulprojekt: Nicht wirklich nötig.

Schwierigkeiten kann die SQL-Syntax im Abfragestring machen. Die unterscheidet sich in Details nämlich, je nachdem, welches System man benutzt:

1. "SELECT * FROM fragen     WHERE aw1    = 'H2O';"
2. "SELECT * FROM \"fragen\" WHERE \"aw1\"= 'H2O';"
3. "SELECT * FROM `fragen`   WHERE `aw1`  = 'H2O';"
4. "SELECT * FROM 'fragen'   WHERE 'aw1'  = 'H2O';"

Bei MS Access funktionieren die Varianten 1, 2 und 3, bei MySQL 1 und 3, bei Base 2, und Variante 4 funktioniert nie (die mit einfachen Apostrophen um Tabellen- und Spaltenbezeichner).
Auch bei der Auswahl von Spalten aus mehreren Tabellen, wie man sie bei Joins braucht, gibt es kleine Syntaxunterschiede.

4. Die Verbindung zur Datenbank

Die Hauptschwierigkeit, habe ich gesagt, ist die Verbindung zur Datenbank. Handelt es sich um eine DB von einem DB-Server, ist das kein Problem. Man schreibt:

//2. Verbindung herstellen
Connection conn = DriverManager.getConnection (
	praefix+"127.0.0.1/MeineDB",
	user,
	kennwort
	);

Und das war’s. Statt IP-Adresse kann man auch gleich Domain/TLD angeben.

Wenn die DB in einer Datei gespeichert ist, ist es schwieriger. Es funktioniert perfekt, den Pfad zur Datei absolut anzugeben:

//2. Verbindung herstellen
Connection conn = DriverManager.getConnection (
	praefix+"C:\Eigene Dateien\MeinProjekt\BlueJ-Projektordner\datenbank.db",
	user,
	kennwort
	);

Nur ist das ja sinnlos, weil ich das Projekt ja anderen Leuten geben möchte, und die haben eine ganz andere Ordnerstruktur. Also brauche ich einen relativen Pfad und keinen absoluten. Es funktioniert zum Beispiel, wenn ich die DB-Datei in mein BlueJ-Projekt platziere:

//2. Verbindung herstellen
Connection conn = DriverManager.getConnection (
	praefix+"datenbank.db",
	user,
	kennwort
	);

Das heißt, es funktioniert zumindest, solange ich mit BlueJ oder Eclipse arbeite. Ich will aber aus dem Projekt irgendwann mal ein .jar-Archiv machen, damit ich es weitergeben kann, und dann kommt plötzlich keine Datenbankverbindung mehr zustande. Der Grund: der relative Pfad in meinem Code ist immer relativ zu dem Verzeichnis, in dem Java gerade ausgeführt wird. Und das ist nicht unbedingt dasjenige, das man erwartet.

Wenn ich durch Doppelklick oder auf der Kommandozeile mein Java-Archiv starte:

C:\Eigene Dateien\MeinProjekt> java -jar projekt.jar

dann ist das aktuelle Verzeichnis C:\Eigene Dateien\MeinProjekt, und da sucht Java nach der Datenbankdatei. Schlimmer noch, ich kann auf der Kommandozeile mein Programm ja auch so starten:

C:\Eigene Dateien> java -jar MeinProjekt\projekt.jar

dann ist das aktuelle Verzeichnis wieder ein anderes, nämlich C:\Eigene Dateien\.

Kurz gesagt: man kann nicht wissen, was das aktuelle Verzeichnis ist. (Außerdem will ich meine Datenbankdatei ohnehin nicht in einem .jar-Archiv haben, sondern außerhalb davon. Auf Material in dem Archiv kann, während es ausgeführt wird, nämlich nur lesend zugegriffen werden, geschrieben werden kann dann nichts in die Datei.)

Das gilt alles genauso für Hintergrundgrafiken. Wenn ich schreibe:

ImageIcon icon = new ImageIcon("bild.jpg");

dann sucht Java im aktuellen Verzeichnis nach der Datei „bild.jpg“ – aber das aktuelle Verzeichnis muss nicht das sein, das man erwartet. Also lässt man sich zuerst die URL der Grafikdatei geben und übergibt die dann dem ImageIcon-Konstruktor:

java.net.URL imageURL = getClass().getResource("bild.jpg");
try{
   ImageIcon icon = new ImageIcon(imageURL);
}

Das geht.
Und so ähnlich muss man es auch mit Datenbankdateien machen, also den absoluten Pfad zur Laufzeit ermitteln. Nur ist das eigentlich nicht vorgesehen. Bei stackoverflow.com bin ich aber auf eine Lösung gestoßen. Mit diesem Code ermittelt man zur Laufzeit den Pfad zu dem Verzeichnis über dem Verzeichnis, in dem Java gerade ausgeführt wird:

private String pfadZumOberverzeichnis() {
    java.security.ProtectionDomain pd = getClass().getProtectionDomain();
    if ( pd == null ) return null;
    java.security.CodeSource cs = pd.getCodeSource();
    if ( cs == null ) return null;
    java.net.URL url = cs.getLocation();
    if ( url == null ) return null;
    java.io.File f = new java.io.File( url.getFile() );
    if (f == null) return null;
 
    String pfad = "";
    try {
        pfad = f.getParentFile().getAbsolutePath();
        pfad = java.net.URLDecoder.decode(pfad, "utf-8");
    } catch (Exception e) { }
    return pfad + "/";
}

Und in dieses Verzeichnis außerhalb von und parallel zum BlueJ-Ordner bzw. außerhalb von und parallel zum .jar-Archiv steckt man die Datenbankdatei. Dann stellt man die Verbindung so her:

//2. Verbindung herstellen
Connection conn = DriverManager.getConnection(
		protokoll+pfadZumOberverzeichnis()+"datenbank.db",
		user,
		kennwort
		);

Inzwischen klappt das mit meinen Datenbanken auf Linux und Windows, als Archiv oder Projekt in der Entwicklungsphase.

(Zum Download: Ein winziges Demoprojekt mit einer Musik-Datenbank aus den ISB-Handreichungen, und eine Präsentation zum Thema von einer Fortbildung, die ich mal gehalten habe.)

Tagged: Tags

11 Thoughts to “Datenbanken und Java in der Schule

  1. Apache Derby könnte auch eine Alternative sein – sehr klein und einfach. Hält sich aber im Gegensatz zu MySQL an die SQL Standards (Heißt z.B. kein LIMIT statement :-) ).

  2. Danke für diesen sehr informativen Artikel, der sich auch mit meinen Erfahrungen im Unterricht, sofern ich sie bisher gemacht habe, decken. Alles ziemlich kompliziert, sobald man nach Lösungen für die Schüler-Rechner zu Hause sucht…
    Ich arbeite daher gerade an einem USB-Stick, der sämtliche Software inkl. XAMP-Server enthält. Dort habe ich zudem HeidiSQL mit drauf, damit die Datenbanken schülerfreundlich editiert werden können. Eingesetzt habe ich das bisher noch nicht, da wir in Niedersachsen Java und DB (noch) nicht verbinden sollen/müssen. Aber es eignet sich sicher gut, wenn sich meine 12er auf das Abi vorbereite, um wieder ins Programmieren zu kommen bei gleichzeitiger Wiederholung der DB-Thematik.

    Vielleicht hast Du aber schon die gleiche Idee mit portabler Software gehabt? Dann würde mich brennend interessieren, ob und welche Probleme es damit gab. Vielleicht bewahrt mich das vor unangenehmen Pannen…

  3. Auf Apache Derby bin ich gestoßen, habe aber nie damit gearbeitet. Sehr viel weiter als ich hier schreibe reicht mein Wissen meist leider nicht… ahem.

    Mit einem XAMPP-Stick und Schülern habe ich keine Erfahrung. Selber arbeite ich gelegentlich mit so einem Stick, funktioniert einwandfrei. (Nur Heidi habe ich nie darauf gepackt.) Mit guten 12ern müsste das schon gehen – die Schüler müssen halt eventuell selbstständig Datenbanken auf den neuesten gemeinsamen Stand bringen können. Andererseits, oft ändern sich die Datenbanken auch nicht. Es kommt wohl darauf an, wie wichtig Datenbanekn fürs Projekt sind. (Bei mir erst mal: gar nicht. Das ist nur dem Lehrplan zuliebe, damit man die Illusion hat, der Neuntklassstoff würde fürs Abitur noch einmal wiederholt.)

  4. Ich würde den Aspekt der Installation und dem Problem mit den relativen Pfaden zunächst ausklammern und nicht in den Mittelpunkt stellen. Schließlich sollen die SuS doch das Programmieren lernen. Wenn auf einmal Umlaute, Leerzeichen oder gar Zeilenumbrüche in Pfadnamen auftauchen, bekommst du wieder neue Probleme.

    Für deine Klasse DBVerbindung ist mir noch eingefallen, dass man dort doch gut Vererbung nutzen könnte. Für jeden Hersteller gibt es eine Subklasse, der die Unterschiede in den Methoden anders implementiert.

    Hast du einen Link zu der Handreichung, die in deinem Artikel erwähnst?

  5. Ja, danke für den inspirativen Artikel!

    Ich arbeite sehr gerne mit MySQL-Workbench, die Schüler kommen auch gut damit klar. Das ist ein massives, mächtiges Werkzeug, das auch in der Praxis verwendet wird; wenn noch ERM auf dem Lehrplan steht, ist die Fähigkeit zu Forward- und Reverse-Engineering eine feine Sache.
    WAMP (o.ä.) lasse ich zuhause installieren, das ist i.d.R. kein Problem.

    Ein zentrales Problem sehe ich wie du darin, Projekt + Datenbank irgendwohin zu verschieben. Letztlich möchte man doch Projekte machen, die irgendwie realistisch sind. Wenn man das Zeug dann nur auf dem Schulrechner rumliegen hat und kein anderer Mensch es benutzen kann, killt das Motivation. Wie funktioniert das mit SQLite?

  6. >Wie funktioniert das mit SQLite?

    Das ist einfache ein verlinkte Datei, die man weitergeben kann. Firefox speichert Cookies zum Beispiel in einer Datei „cookies.sqlite“, die man sich mit dem Firefox-Addon „SQLite Manager“ einfach anschauen kann; dann sieht man die Tabellen und Einträge und kann sie mit SQL-Syntax bearbeiten.

  7. Hallo,
    ich habe mal mit Xdev experimentiert und auf eine MySQL-DB zugegriffen.
    (http://cms.xdev-software.de). Das Tool ist OpenSource und ganz interessant, wenn es um schnelle Fortschritte in der Verbindung von DB und GUI geht. Hier gibt es auch ein Mapping der relationalen Tabellen auf virtuelle Tabellen, auf die die GUI dann zugreift.
    Evtl. stelle ich es im nächsten Schuljahr bei meinen Technikerschülern mal für eine Projektarbeit vor und lasse sie damit experimentieren.
    Die Dokumentation bzw. Beispiele sind online verfügbar: http://cms.xdev-software.de/xdevdoku/HTML/
    Bald soll das Release für Xdev4 erscheinen, ich arbeite zur Zeit mit der Beta.
    Xdev kann auf alle möglichen DBs zugreifen u. hat auch eine integrierte DB.
    Ist ein sehr mächtiges Tool und benötigt etwas längere Einarbeitung. Aber gerade die Entwicklung einer DB-Anwendung mit Java wird hier sehr gut unterstützt.

  8. Sieht nach einem schönen Werkzeug aus, wenn man sich ernsthaft mit DB beschäftigt. Für das Projekt in der 11. ist es zu mächtig, da sehe ich DB nur als Lehrplanartefakt, um irgendwie die 9. Klasse in Erinnerung zu rufen.

  9. Danke für den Tipp mit dem SQLite Database Browser. Ich habe lange nach einem Werkzeug gesucht, das die Lernenden nutzen können um SQL Anfragen zu entwickeln und zu testen. LibreOffice Base war mir zu überladen und die SQL Anfragen ließen sich nicht so schön erstellen. Für MySQL und phpMyAdmin hatte ich keine Lust einen Server zu installieren.

    Ob ich die Autovervollständigung als hilfreich oder nicht empfinde weiß ich noch nicht. Das muss ich erst einmal testen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.