{"id":4267,"date":"2013-08-11T08:04:14","date_gmt":"2013-08-11T06:04:14","guid":{"rendered":"https:\/\/www.herr-rau.de\/wordpress\/?p=4267"},"modified":"2023-05-24T09:35:15","modified_gmt":"2023-05-24T07:35:15","slug":"datenbanken-und-java-in-der-schule","status":"publish","type":"post","link":"https:\/\/www.herr-rau.de\/wordpress\/2013\/08\/datenbanken-und-java-in-der-schule.htm","title":{"rendered":"Datenbanken und Java in der Schule"},"content":{"rendered":"<div style='text-align:right;'><small>(<a href='https:\/\/www.herr-rau.de\/wordpress\/2013\/08\/datenbanken-und-java-in-der-schule.htm#comments'>13 Kommentare.<\/a>)<\/small> <\/div>\n<p>In der 11. Jahrgangsstufe sollen die Sch\u00fcler 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\u00f6rsensimulation und einen Fahrradroutenplaner zur Verf\u00fcgung; ich habe schon mal mit Sch\u00fclern <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2010\/10\/programmierprojekt-in-der-q11.htm\">zwei sch\u00f6ne Projekte gemacht<\/a> und bin mit zwei anderen gescheitert. Dabei spielt die Datenbank f\u00fcr mich keine gro\u00dfe Rolle; sie hat absolut nichts mit dem Lehrplan von Q11 oder Q12 zu tun, die Sch\u00fcler interessieren sich nicht daf\u00fcr, und f\u00fcr 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.<\/p>\n\n\n\n<p>Java und SQL-Datenbanken in der Schule haben einige T\u00fccken, wie ich nach und nach herausgefunden habe. Mit etwas Basteln funktionierte das Projekt &#8211; zumindest in der Schule, aber nicht unbedingt bei den Sch\u00fclern zu Hause, und nicht unter einem anderen Betriebssysteme, oder auch nur innerhalb der Entwicklungsumgebung und nicht als eigenst\u00e4niges Java-Produkt. Ich schreibe hier mal zusammen, was ich herausgefunden habe.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Wahl des Datenbanksystems: Access, MySQL, SQLite, Base?<\/li>\n\n\n\n<li>Integrieren des passenden Treibers<\/li>\n\n\n\n<li>Grunds\u00e4tzliche Aufbau einer Anfrage: Unterschiede bei der Syntax<\/li>\n\n\n\n<li>Die Verbindung zur Datenbank: Hauptproblem Speic1herort bei lokalen Dateien<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">1. Wahl des Datenbanksystems<\/h3>\n\n\n\n<p>Es gibt viele M\u00f6glichkeiten, mit SQL-Syntax zu arbeiten.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">MS Access<\/h4>\n\n\n\n<p><strong>Vorteile:<\/strong> Treiber ist bereits vorhanden. Man kann die Datenbank leicht au\u00dferhalb von Java bearbeiten.<br><strong>Nachteile:<\/strong> L\u00e4uft nur unter Windows und nur, wenn Access installiert ist.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">MySQL-Server<\/h4>\n\n\n\n<p><strong>Vorteile:<\/strong> L\u00e4uft bei allen Betriebssystemen. Man hat keine Probleme mit dem Speicherort der DB (siehe sp\u00e4ter).<br><strong>Nachteile:<\/strong> Man muss den richtigen Treiber finden; man braucht sch\u00fclerferne 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\u00fclern schon weniger, und weitergeben an Eltern und Freunde kann man das Programm dann auch nur, wenn man denen die Serverinfrastruktur mitgibt.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Open Office Base<\/h4>\n\n\n\n<p><strong>Vorteile:<\/strong> L\u00e4uft bei allen Betriebssystemen. Man kann die DB leicht in Base erstellen.<br><strong>Nachteile:<\/strong> 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 <code>database<\/code> enth\u00e4lt. Dieser Ordner enth\u00e4lt die 4 Dateien <code>backup, data, properties<\/code> und <code>script<\/code>. Die muss man auspacken und umbenennen in zum Beispiel <code>xxx.backup, xxx.data, xxx.properties<\/code> und <code>xxx.script<\/code> &#8211; und dann erst kann Java mit der Datenbank unter dem Namen <code>xxx<\/code> im HSQLDB-Format arbeiten.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">SQLite<\/h4>\n\n\n\n<p><strong>Vorteile:<\/strong> L\u00e4uft bei allen Betriebssystemen.<br><strong>Nachteile:<\/strong> Man muss den richtigen Treiber finden. Es bietet nur eine &#8211; f\u00fcr die Schule aber voll ausreichende &#8211; Teilmenge von SQL; es gibt keine Fremdschl\u00fcssel und keine Kontrolle der Typen &#8211; um die Datenintegrit\u00e4t muss man sich selber k\u00fcmmern. Zum Erstellen und Warten der DB braucht man ein eigenes Programm, davon gibt es aber genug, etwa den SQLite Database Browser.<\/p>\n\n\n\n<p>&#8212; Inzwischen neige ich zu SQLite.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Integrieren des Treibers<\/h3>\n\n\n\n<p>Wenn man sich f\u00fcr 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\u00fcr gibt es verschiedene M\u00f6glichkeiten. In BlueJ bindet man die Datei als Bibliothek ein, oder man kopiert sie in einen Ordner namens <code>+libs<\/code> im BlueJ-Projektverzeichnis.)<\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td>DB-Typ<\/td><td>Treiberbezeichner<\/td><td>Pr\u00e4fix<\/td><td>Treiber zu finden z.B. in<\/td><\/tr><tr><td>MS Access<\/td><td>&#8222;sun.jdbc.odbc.JdbcOdbcDriver&#8220;<\/td><td>&#8222;jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=&#8220;<\/td><td>-integriert-<\/td><\/tr><tr><td>MySQL<\/td><td>&#8222;com.mysql.jdbc.Driver&#8220;<\/td><td>&#8222;jdbc:mysql:\/\/&#8220;<\/td><td>mysql-connector-java-5.1.25-bin.jar<\/td><\/tr><tr><td>Base<\/td><td>&#8222;org.hsqldb.jdbcDriver&#8220;<\/td><td>&#8222;jdbc:hsqldb:&#8220;<\/td><td>hsqldb.jar<\/td><\/tr><tr><td>SQLite<\/td><td>&#8222;org.sqlite.JDBC&#8220;<\/td><td>&#8222;jdbc:sqlite:&#8220;<\/td><td>sqlite-jdbc-3.7.2.jar<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Neben dem Treiber selber brauchte man in fr\u00fcheren Java-Versionen dessen Bezeichner, und man braucht immer noch einen Pr\u00e4fix dazu, der beim Einbauen dem Namen der DB vorangestellt wird.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Grunds\u00e4tzliche Aufbau einer Anfrage<\/h3>\n\n\n\n<p>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 <code>quiz.sqlite<\/code>, aber dazu sp\u00e4ter mehr.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import java.sql.*;\n\nclass DBVerbindung {\n  \/\/Attribute\n  String treiberbezeichner = \"org.sqlite.JDBC\";\n  String praefix = \"jdbc:sqlite:\";\n  String urlstring = \"quiz.sqlite\";\n  String user = \"\";\n  String kennwort = \"\";\n\n  \/\/Anfragestring zu Demo-Zwecken hier ausgelagert\n  String anfragestring = \"SELECT * FROM fragen WHERE antwort1='H2O';\";\n  String spaltenbezeichner = \"frage\";\n\n  void test() {\n    try {\n      \/\/1. Treiber laden\n      Class.forName(treiberbezeichner);\n\n      \/\/2. Verbindung herstellen\n      Connection conn = DriverManager.getConnection(praefix+urlstring, user, kennwort);\n\n      \/\/3. Statement erzeugen\n      Statement stmt = conn.createStatement();\n\n      \/\/4. Abfrage durchfuehren und Ergebnismenge erhalten\n      ResultSet rset = stmt.executeQuery(anfragestring);\n      \/\/bzw. stmt.executeUpdat(auftragInSQL)\n\n      \/\/5. Ergebnismenge verarbeiten (in Schleife, mit getInt\/getString)\n      while (rset.next()) { System.out.println (rset.getString(spaltenbezeichner)); }\n\n      \/\/6. Ergebnismenge schliessen\n      rset.close();\n\n      \/\/7. Statement schliessen\n      stmt.close();\n\n      \/\/8. Verbindung schliessen\n      conn.close();\n    }\n    catch (Exception e) {\n      System.out.println(e);\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Den Schritt 1 kann man in neueren Java-Versionen weglassen, da Java den Treiber automatisch l\u00e4dt, wenn er den Pr\u00e4fix korrekt zuordnen kann. Schritt 2, der Aufbau der Verbindung zur Datenbank, macht am meisten Schwierigkeiten, dazu sp\u00e4ter. Schritt 4 und 5 sind das Stellen und Verarbeiten der SQL-Abfrage. Hier kann man nat\u00fcrlich optimieren, wenn man sich f\u00fcr geschickte SQL-Abfragen interessiert. F\u00fcr ein Schulprojekt: Nicht wirklich n\u00f6tig.<\/p>\n\n\n\n<p>Schwierigkeiten kann die SQL-Syntax im Abfragestring machen. Die unterscheidet sich in Details n\u00e4mlich, je nachdem, welches System man benutzt:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>1. \"SELECT * FROM fragen     WHERE aw1    = 'H2O';\"\n2. \"SELECT * FROM \\\"fragen\\\" WHERE \\\"aw1\\\"= 'H2O';\"\n3. \"SELECT * FROM `fragen`   WHERE `aw1`  = 'H2O';\"\n4. \"SELECT * FROM 'fragen'   WHERE 'aw1'  = 'H2O';\"<\/code><\/pre>\n\n\n\n<p>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).<br>Auch bei der Auswahl von Spalten aus mehreren Tabellen, wie man sie bei Joins braucht, gibt es kleine Syntaxunterschiede.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. Die Verbindung zur Datenbank<\/h3>\n\n\n\n<p>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:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/2. Verbindung herstellen\nConnection conn = DriverManager.getConnection (\n  praefix+\"127.0.0.1\/MeineDB\",\n  user,\n  kennwort\n  );<\/code><\/pre>\n\n\n\n<p>Und das war&#8217;s. Statt IP-Adresse kann man auch gleich Domain\/TLD angeben.<\/p>\n\n\n\n<p>Wenn die DB in einer Datei gespeichert ist, ist es schwieriger. Es funktioniert perfekt, den Pfad zur Datei absolut anzugeben:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/2. Verbindung herstellen\nConnection conn = DriverManager.getConnection (\n  praefix+\"C:\\Eigene Dateien\\MeinProjekt\\BlueJ-Projektordner\\datenbank.db\",\n  user,\n  kennwort\n  );<\/code><\/pre>\n\n\n\n<p>Nur ist das ja sinnlos, weil ich das Projekt ja anderen Leuten geben m\u00f6chte, und die haben eine ganz andere Ordnerstruktur. Also brauche ich einen <em>relativen<\/em> Pfad und keinen absoluten. Es funktioniert zum Beispiel, wenn ich die DB-Datei in mein BlueJ-Projekt platziere:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/2. Verbindung herstellen\nConnection conn = DriverManager.getConnection (\n  praefix+\"datenbank.db\",\n  user,\n  kennwort\n  );<\/code><\/pre>\n\n\n\n<p>Das hei\u00dft, 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\u00f6tzlich keine Datenbankverbindung mehr zustande. Der Grund: der relative Pfad in meinem Code ist immer <strong>relativ zu dem Verzeichnis, in dem Java gerade ausgef\u00fchrt wird.<\/strong> Und das ist nicht unbedingt dasjenige, das man erwartet.<\/p>\n\n\n\n<p>Wenn ich durch Doppelklick oder auf der Kommandozeile mein Java-Archiv starte:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>C:\\Eigene Dateien\\MeinProjekt&gt; java -jar projekt.jar<\/code><\/pre>\n\n\n\n<p>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:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>C:\\Eigene Dateien&gt; java -jar MeinProjekt\\projekt.jar<\/code><\/pre>\n\n\n\n<p>dann ist das aktuelle Verzeichnis wieder ein anderes, n\u00e4mlich C:\\Eigene Dateien\\.<\/p>\n\n\n\n<p>Kurz gesagt: man kann nicht wissen, was das aktuelle Verzeichnis ist. (Au\u00dferdem will ich meine Datenbankdatei ohnehin nicht in einem .jar-Archiv haben, sondern au\u00dferhalb davon. Auf Material in dem Archiv kann, w\u00e4hrend es ausgef\u00fchrt wird, n\u00e4mlich nur lesend zugegriffen werden, geschrieben werden kann dann nichts in die Datei.)<\/p>\n\n\n\n<p>Das gilt alles genauso f\u00fcr Hintergrundgrafiken. Wenn ich schreibe:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ImageIcon icon = new ImageIcon(\"bild.jpg\");<\/code><\/pre>\n\n\n\n<p>dann sucht Java im aktuellen Verzeichnis nach der Datei &#8222;bild.jpg&#8220; &#8211; aber das aktuelle Verzeichnis muss nicht das sein, das man erwartet. Also l\u00e4sst man sich zuerst die URL der Grafikdatei geben und \u00fcbergibt die dann dem ImageIcon-Konstruktor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>java.net.URL imageURL = getClass().getResource(\"bild.jpg\");\ntry {\n  ImageIcon icon = new ImageIcon(imageURL);\n}<\/code><\/pre>\n\n\n\n<p>Das geht.<br>Und so \u00e4hnlich 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 <a href=\" http:\/\/stackoverflow.com\/questions\/16076911\/how-to-find-absolute-path-from-a-relative-path-in-file-system\">auf eine L\u00f6sung gesto\u00dfen.<\/a> Mit diesem Code ermittelt man zur Laufzeit den Pfad zu dem Verzeichnis <em>\u00fcber<\/em> dem Verzeichnis, in dem Java gerade ausgef\u00fchrt wird:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private String pfadZumOberverzeichnis() {\n  java.security.ProtectionDomain pd = getClass().getProtectionDomain();\n  if ( pd == null ) return null;\n  java.security.CodeSource cs = pd.getCodeSource();\n  if ( cs == null ) return null;\n  java.net.URL url = cs.getLocation();\n  if ( url == null ) return null;\n  java.io.File f = new java.io.File( url.getFile() );\n  if (f == null) return null;\n\n  String pfad = \"\";\n  try {\n    pfad = f.getParentFile().getAbsolutePath();\n    pfad = java.net.URLDecoder.decode(pfad, \"utf-8\");\n  } catch (Exception e) { }\n  return pfad + \"\/\";\n}<\/code><\/pre>\n\n\n\n<p>Und in dieses Verzeichnis au\u00dferhalb von und parallel zum BlueJ-Ordner bzw. au\u00dferhalb von und parallel zum .jar-Archiv steckt man die Datenbankdatei. Dann stellt man die Verbindung so her:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/2. Verbindung herstellen\nConnection conn = DriverManager.getConnection(\n  protokoll+pfadZumOberverzeichnis()+\"datenbank.db\",\n  user,\n  kennwort\n  );<\/code><\/pre>\n\n\n\n<p>Inzwischen klappt das mit meinen Datenbanken auf Linux und Windows, als Archiv oder Projekt in der Entwicklungsphase.<\/p>\n\n\n\n<p>(Zum Download: <a href=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/Datenbankanbindung_Java.zip\">Ein winziges Demoprojekt mit einer Musik-Datenbank aus den ISB-Handreichungen, und eine Pr\u00e4sentation zum Thema von einer Fortbildung, die ich mal gehalten habe.<\/a>)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(13 Kommentare.) In der 11. Jahrgangsstufe sollen die Sch\u00fcler 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\u00f6rsensimulation und einen Fahrradroutenplaner zur Verf\u00fcgung; ich habe schon mal mit Sch\u00fclern zwei sch\u00f6ne Projekte gemacht und bin mit zwei anderen [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25],"tags":[227],"class_list":["post-4267","post","type-post","status-publish","format-standard","hentry","category-informatik","tag-informatik"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/4267","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/comments?post=4267"}],"version-history":[{"count":2,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/4267\/revisions"}],"predecessor-version":[{"id":57520,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/4267\/revisions\/57520"}],"wp:attachment":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media?parent=4267"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/categories?post=4267"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/tags?post=4267"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}