www.r-krell.de
Webangebot für Schule und Unterricht, Software, Fotovoltaik und mehr

Willkommen/Übersicht  >  Informatik  >  

Datenbanken

Teil 3: Datenbanken aus und für Java-Anwendungen verwenden



Die Ausführungen über Datenbanken ergänzen meine Reihe „Informatik mit Java".

Auf der vorangegangenen Seiten "Datenbanken, Teil 1" gab es die Übersicht und sinnvolle Software und auf "Datenbanken, Teil 2": Entwurf, Normalisierung, ERD und SQL-Abfragen wurden theoretische Konzepte sowie praktische Übungen mit MySQL und dem MySQL-QueryBrowser vorgestellt.

Auf dieser vorerst letzten Datenbank-Seite "Datenbanken, Teil 3" finden Sie:


zum Seitenanfang / zum Seitenende

Datenbanken und Java
-- getrennte Welten und vorteilhafte Symbiose

1) MySQL als Server -- Bedienung durch Clients

Die Datenbank-Software MySQL arbeitet als Server, d.h. MySQL stellt die Datenbankdienste zur Verfügung und übernimmt das Speichern und Verwalten der Daten. Allerdings arbeitet diese Software auch nach dem Start servergemäß im Hintergrund und hat keine eigene Oberfläche. Um MySQL zu nutzen und zu bedienen, muss deswegen ein so genanntes Client-Programm verwendet werden, das Befehle vom Menschen entgegen nimmt und an MySQL übermittelt, dort die zur Verfügung gestellten Dienste nachfragt bzw. ausführen lässt und schließlich die von MySQL gelieferten Antworten und Ausgaben in eigenen Fenstern sinnvoll anzeigt. Oft wird der im XAMPP-Paket vorhandene PHP-Client dazu genutzt. Auf meinen beiden voran gegangen Datenbank-Seiten wurde aber der MySQL-QueryBrowser aus den MySQL-GUI-Tools verwendet, der auch hier nochmal zum Einsatz kommt. Grundsätzlich ist es egal, welcher Client verwendet wird und in welcher Sprache der Client geschrieben ist, sofern einige elementare Kommunikationsregeln eingehalten werden. Insofern ist es auch leicht möglich, selbst einen Client in Java zu schreiben und so den Datenbankzugriff und die Bedienung von MySQL aus einem eigenen Java-Programm heraus zu realisieren.

Im Folgenden soll ein solches Programm entwickelt und vorgestellt werden.

zum Seitenanfang / zum Seitenende

2) Datenbankformate als gute Wahl bei allen komplexen Speicherungen

Beherrscht man einmal den Datenbankzugriff aus Java heraus, bietet sich allerdings auch an, bei vielen anderen Programmen und Anwendungen -- etwa der im Teil d) meiner Seiten "Informatik mit Java" beschriebenen Adress- und Fuhrpark-Verwaltung -- die Daten nicht per writeObject-Anweisungen in einem javaeigenen Format auf der Festplatte zu speichern, sondern direkt in einer (MySQL-)Datenbank abzulegen. Die Datenbank-Formate sind nämlich deutlich langlebiger bzw. zukunftssicherer und Daten können notfalls auch mit anderen Programmen gelesen und bearbeitet werden. Bei Java reicht hingegen oft schon das Neukompilieren der Anwendung in einer neuen Java-Version, dass sich die Serialisierung der Objekte ändert und alte Daten nicht mehr gelesen werden können und praktisch verloren sind. Insofern bringt das Speichern in einer Datenbank dauerhafte Datensicherheit und Unabhängigkeit; künftige Weiterentwicklungen könnten auch in anderen Sprachen geschehen und trotzdem noch den vorhandenen Datenbestand nutzen. Außerdem brauchen Methoden etwa zum Sortieren oder Filtern der Daten nicht mehr mühsam und fehleranfällig selbst geschrieben und programmiert werden, sondern es kann bequem auf die weithin bekannten, vielfach erklärten und längst ausgetesteten SQL-Befehle zurück gegriffen werden. Deshalb sollten Daten eigentlich bei allen vernünftigen Programmen entweder in reiner Textform oder -- bei strukturierten Daten -- in einer Datenbank gespeichert werden! Die Verwendung eigener, 'generischer' Formate, die früher vielleicht einmal Platz- oder Zeitvorteile boten, ist angesichts heutiger Rechnerausstattungen nicht mehr zeitgemäß und einfach auch zu risikoreich.

zum Seitenanfang / zum Seitenende



3) Voraussetzungen MySQL und Java-MySQL-Connector/J

Weil das Java-Programm 'nur' als Client arbeitet, muss für den Datenbankzugriff immer gleichzeitig MySQL als Server im Hintergrund laufen. Um die richtige Kommunikation zwischen Server und Client braucht sich der Java-Programmierer bzw. die Anwendungs-Programmiererin nicht kümmern, dies übernimmt der Java-MySQL-Connector, der einmal ins System eingebunden wird (der Download und die einmalige Installation des MySQL-Connectors wurden im Teil 1 meiner Datenbank-Seiten bereits beschrieben). Fertige, von Sun/Oracle bzw. mit der Java-JDK mitgelieferte Bibliotheksbefehle (aus dem Paket java.sql) erlauben die Weitergabe und das Auswerten von Datenbank-Befehlen. Der Programmierer kann sich daher auf seine übliche Aufgabe, die Konstruktion einer ansprechenden und zweckdienlichen Benutzeroberfläche und das Hinterlegen der Schaltflächen mit geeigneten Funktionen kümmern.




zum Seitenanfang / zum Seitenende

Ein Java-Programm
mit Datenbankzugriff auf MySQL


Um grundlegende Möglichkeiten zu demonstrieren, wurde ein Java-Programm entwickelt, das eine Datenbank namens TestJDB einrichtet und darin beispielhaft eine kleine Tabelle Kunde anlegt und mit einigen Datensätzen füllt. Ist die Datenbank TestJDB schon vorhanden, kann das Programm damit verbinden und sie weiter nutzen. Vom Benutzer in übliche Textfelder eingegebene Daten können zu Datensätzen verbunden und in der Datenbank bzw. dort in der Tabelle Kunde gespeichert werden; natürlich können die Daten auch wieder geholt und angezeigt werden. Außerdem soll die Eingabe beliebiger SQL-Befehle durch den Benutzer möglich sein, womit weitere Datenbanken erstellt und verändert, Tabellen angelegt, manipuliert und abgefragt werden können.

Auf dieser Webseite stelle ich den vollständige Programmtext vor. Das Programm umfasst zwei Klassen, beschrieben in den Dateien DBJ_JOberflaeche.java [Quelltext hier zusammenhängend auf türkisfarbenem Hintergrund dargestellt] und DBJ_JFunktion.java [weißer Hintergrund; verteilt auf die Abschnitte 1) bis 8) im nächsten Kapitel: der Quelltext wird jeweils von Kommentaren unterbrochen]. Ein Reiter im folgenden Bild kündet noch von der Existenz der Datei DBJ_JOberflaeche.jfm -- hierin speichert der Javaeditor das Formular, auf dem die Oberfläche mit der Maus hergestellt und verändert werden kann. Dieses Formular ist aber nicht nötig, um das Programm laufen zu lassen. Alle Informationen aus der .jfm-Datei finden automatisch ihren Niederschlag im Programmtext in DBJ_JOberflaeche. Wer also den folgenden Programmtext kopiert, kann ihn in jeder beliebigen Java-Entwicklungsumgebung neu kompilieren und das Programm laufen lassen. Noch bequemer ist allerdings der Test durch Download der fertigen jar-Datei weiter unten im Kapitel "Der Programmstart".

Die Oberfläche wurde mit dem Javaeditor (hier mit der Version 9.14p) im Wesentlichen per Drag-and-Drop erzeugt. Bezugsmöglichkeiten und Einrichtung des Javaeditors sind auf meiner Seite "Informatik mit Java, Teil a): Grundlegendes zu Java, benötigte Software und deren Installation" genannt -- wie gerade gesagt, kann aber auch jede andere Javaentwicklungsumgebung oder notfalls sogar ein einfacher Texteditor genutzt werden. Das folgende Bild zeigt aber die Arbeit an der Benutzer-Oberfläche im Javaeditor. Während der Javaeditor die in die Oberfläche gezogenen Komponenten automatisch etwa mit jLabel1, jLabel2 usw. bezeichnet, habe ich im Objekt-Inspektor jeweils sprechende Namen gegeben (und den Typ als Kürzel vorangestellt): so ist jLbKundenNr das Label, das den Text "KundenNr:" auf der Oberfläche anzeigt, jTfKundenNr das Textfeld, in das der Benutzer die Kundennummer eingeben kann und so wäre jBtKundenNr der Button bzw. die Schaltfläche, mit der etwa die Kundennummer bestätigt werden müsste, falls dafür eine Schaltfläche vorgesehen wäre. Das kleine j im Präfix macht deutlich, dass hier nicht AWT-, sondern Swing-Komponenten in eine von JFrame abgeleitete Oberfläche eingebunden werden.



Erstellen der grafischen Oberfläche in der Javeditor-Entwicklungsumgebung (Screenshot)

Die Benutzer-Oberfläche DBJ_JOberflaeche enthält zwar alle Bedienelemente und zugehörige Methoden, soweit sie sich auf die Darstellung beziehen, ruft aber zur Erledigung der Aufgaben Methoden des eingebundenen Objekts db der Klasse DBJ_JFunktion auf. Denn in der letzten Klasse habe ich die eigentlichen Methoden zur Datenbankmanipulation und -abfrage zusammen gefasst, die dort unabhängig von der Oberfläche stehen.


zum Seitenanfang / zum Seitenende

Die grafische Benutzer-Oberfläche DBJ_JOberflaeche

1) Der Quelltext der Oberfläche

Wie im vorstehenden Abschnitt schon erläutert, wurde der Quelltext der Oberfläche weitgehend automatisch vom Javaeditor erzeugt, während ich die Bedienelemente per Mausklick bzw. Ziehen und Ablegen auf dem Formular angeordnet und im Objekt-Inspektor benannt bzw. beschriftet habe.

Von Hand eingefügt wurde die Zeile 040 (Einbinden des Objekts db mit der Funktionalität) sowie die Java-Texte in die Methoden ab Zeile 191. Etwas länger ist der Text in den Zeilen 209 bis 245, weil beim Betätigen des "O.K."-Buttons für das Hinzufügen einer weiteren Person in die Kunden-Tabelle eine Überprüfung der Eingaben vorgenommen wird und der Benutzer ggf. auf Fehler hingewiesen wird. Im Prinzip hätte der Text Zeilen 209 bis 245 schon an Stelle der Zeile 133 eingesetzt werden können, aber der Javaeditor trägt automatisch in die ActionPerformed-Methode jeder Schaltfläche einen Methodenaufruf auf eine später leer erstellte Methode wie etwa jBtOK_ActionPerformed ein, damit die vom Programmierer auszufüllenden Teile übersichtlich ab Zeile 191 hinter dem Konstruktor stehen.


001 import java.awt.*;
002 import java.awt.event.*;
003 import javax.swing.*;
004 import javax.swing.event.*;
005 
006 /**
007   *
008   * Demonstration, wie mit einem Java-Programm eine MySQL-Datenbank angelegt,
009   * abgefragt und manipuliert werden kann
010   *
011   * @version 1.0 from 12.06.2010
012   * @author Robert Krell (www.r-krell.de)
013   */
014 
015 public class DBJ_JOberflaeche extends JFrame {
016   // Anfang Attribute
017   private JLabel jLbUeberschrift = new JLabel();
018   private JButton jBtVoraussetzungen = new JButton();
019   private JLabel jLbDatenbank = new JLabel();
020   private JButton jBtCreate = new JButton();
021   private JButton jBtUse = new JButton();
022   private JButton jBtSelectAll = new JButton();
023   private JLabel jLbNeuerKunde = new JLabel();
024   private JLabel jLbKundenNr = new JLabel();
025   private JTextField jTfKundenNr = new JTextField();
026   private JLabel jLbName = new JLabel();
027   private JTextField jTfName = new JTextField();
028   private JLabel jLbAlter = new JLabel();
029   private JTextField jTfAlter = new JTextField();
030   private JButton jBtOK = new JButton();
031   private JButton jBtAbbrechen = new JButton();
032   private JLabel jLbSQLBefehl = new JLabel();
033   private JTextField jTfSQLBefehl = new JTextField();
034   private JButton jBtAusfuehren = new JButton();
035   private JButton jBtVerwerfen = new JButton();
036   private JScrollPane jScrollPane1 = new JScrollPane();
037     private JTextArea jTaAusgabe = new JTextArea("");
038   private JLabel jLbCopyright = new JLabel();
039   
040   DBJ_JFunktion db = new DBJ_JFunktion(); 
041 
042   // Ende Attribute
043 
044   public DBJ_JOberflaeche (String title) {
045     super (title);
046     setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
047     int frameWidth = 787;
048     int frameHeight = 726;
049     setSize(frameWidth, frameHeight);
050     Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
051     int x = (d.width - getSize().width) / 2;
052     int y = (d.height - getSize().height) / 2;
053     setLocation(x, y);
054     Container cp = getContentPane();
055     cp.setLayout(null);
056     // Anfang Komponenten
057     jLbUeberschrift.setBounds(241652524);
058     jLbUeberschrift.setText("Manipulation von und Zugriff auf MySQL-Datenbanken mit Java");
059     jLbUeberschrift.setFont(new Font("MS Sans Serif", Font.PLAIN, 17));
060     cp.add(jLbUeberschrift);
061     jBtVoraussetzungen.setBounds(5921616125);
062     jBtVoraussetzungen.setText("Voraussetzungen");
063     jBtVoraussetzungen.addActionListener(new ActionListener() {
064       public void actionPerformed(ActionEvent evt) {
065         jBtVoraussetzungen_ActionPerformed(evt);
066       }
067     });
068     jBtVoraussetzungen.setToolTipText("Gibt Hilfetext aus");
069     cp.add(jBtVoraussetzungen);
070     jLbDatenbank.setBounds(245615920);
071     jLbDatenbank.setText("Datenbank 'TestJDB': ");
072     jLbDatenbank.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
073     cp.add(jLbDatenbank);
074     jBtCreate.setBounds(2085616325);
075     jBtCreate.setText("TestJDB neu erstellen");
076     jBtCreate.addActionListener(new ActionListener() {
077       public void actionPerformed(ActionEvent evt) {
078         jBtCreate_ActionPerformed(evt);
079       }
080     });
081     jBtCreate.setToolTipText("Erzeugt erstmalig die Datenbank 'TestJDB' mit der Tabelle 'Kunde' und drei Einträgen");
082     cp.add(jBtCreate);
083     jBtUse.setBounds(4005616325);
084     jBtUse.setText("TestJDB benutzen");
085     jBtUse.addActionListener(new ActionListener() {
086       public void actionPerformed(ActionEvent evt) {
087         jBtUse_ActionPerformed(evt);
088       }
089     });
090     jBtUse.setToolTipText("Verbindet mit der (vorhandenen) Datenbank 'TestJDB'");
091     cp.add(jBtUse);
092     jBtSelectAll.setBounds(5925616325);
093     jBtSelectAll.setText("Tabelle 'Kunde' zeigen ");
094     jBtSelectAll.addActionListener(new ActionListener() {
095       public void actionPerformed(ActionEvent evt) {
096         jBtSelectAll_ActionPerformed(evt);
097       }
098     });
099     jBtSelectAll.setToolTipText("Zeigt alle Spalten und Zeilen der Tabelle 'Kunde'");
100     cp.add(jBtSelectAll);
101     jLbNeuerKunde.setBounds(248866820);
102     jLbNeuerKunde.setText("Aufnehmen eines weiteren Kunden in die Datenbank 'TestJDB' bzw. dort in die Tabelle 'Kunde':");
103     jLbNeuerKunde.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
104     cp.add(jLbNeuerKunde);
105     jLbKundenNr.setBounds(321127920);
106     jLbKundenNr.setText("KundenNr.:");
107     jLbKundenNr.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
108     cp.add(jLbKundenNr);
109     jTfKundenNr.setBounds(1121126524);
110     jTfKundenNr.setText("4");
111     jTfKundenNr.setToolTipText("Bitte tragen Sie hier eine (bisher unbenutzte) ganzzahlige Kundennummer ein!");
112     cp.add(jTfKundenNr);
113     jLbName.setBounds(2081124620);
114     jLbName.setText("Name:");
115     jLbName.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
116     cp.add(jLbName);
117     jTfName.setBounds(25611218524);
118     jTfName.setText("Müller");
119     jTfName.setToolTipText("Geben Sie hier einen (Nach-)Namen ein!");
120     cp.add(jTfName);
121     jLbAlter.setBounds(4641124420);
122     jLbAlter.setText("Jahre:");
123     jLbAlter.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
124     cp.add(jLbAlter);
125     jTfAlter.setBounds(5121124924);
126     jTfAlter.setText("16");
127     jTfAlter.setToolTipText("Bitte tragen Sie hier ein ganzzahliges Alter ein!");
128     cp.add(jTfAlter);
129     jBtOK.setBounds(5921125725);
130     jBtOK.setText("O.K.");
131     jBtOK.addActionListener(new ActionListener() {
132       public void actionPerformed(ActionEvent evt) {
133         jBtOK_ActionPerformed(evt);
134       }
135     });
136     jBtOK.setToolTipText("Nimmt Kundendaten in Datenbank-Tabelle auf ");
137     cp.add(jBtOK);
138     jBtVerwerfen.setBounds(41620810525);
139     jBtVerwerfen.setText("Verwerfen");
140     jBtVerwerfen.addActionListener(new ActionListener() {
141       public void actionPerformed(ActionEvent evt) {
142         jBtVerwerfen_ActionPerformed(evt);
143       }
144     });
145     jBtVerwerfen.setToolTipText("Löscht die Eingabezeile, ohne den Befehl auszuführen");
146     cp.add(jBtVerwerfen);
147 
148     jLbSQLBefehl.setBounds(241528720);
149     jLbSQLBefehl.setText("SQL-Befehl:");
150     jLbSQLBefehl.setFont(new Font("MS Sans Serif", Font.PLAIN, 15));
151     cp.add(jLbSQLBefehl);
152     jTfSQLBefehl.setBounds(2417672924);
153     jTfSQLBefehl.setText("delete from kunde where name='Müller';");
154     jTfSQLBefehl.setToolTipText("Geben Sie hier einen eigenen SQL-Befehl ein");
155     cp.add(jTfSQLBefehl);
156     jBtAusfuehren.setBounds(28020811325);
157     jBtAusfuehren.setText("Ausführen");
158     jBtAusfuehren.addActionListener(new ActionListener() {
159       public void actionPerformed(ActionEvent evt) {
160         jBtAusfuehren_ActionPerformed(evt);
161       }
162     });
163     jBtAusfuehren.setToolTipText("Führt den eingegebenen SQL-Befehl aus");
164     cp.add(jBtAusfuehren);
165     jBtAbbrechen.setBounds(6561129925);
166     jBtAbbrechen.setText("Abbrechen");
167     jBtAbbrechen.addActionListener(new ActionListener() {
168       public void actionPerformed(ActionEvent evt) {
169         jBtAbbrechen_ActionPerformed(evt);
170       }
171     });
172     jBtAbbrechen.setToolTipText("Löscht Eingaben, ohne Kunden aufzunehmen");
173     cp.add(jBtAbbrechen);
174     jScrollPane1.setBounds(24256729353);
175     cp.add(jScrollPane1);
176     jTaAusgabe.setBounds(-10, -2729353);
177     jTaAusgabe.setText("");
178     jScrollPane1.setViewportView(jTaAusgabe);
179     jTaAusgabe.setEditable(false);
180     jTaAusgabe.setFont(new Font("monospaced"012));
181     jTaAusgabe.setToolTipText("In diesem Feld erfolgt die Ausgabe des Programms -- hier sind keine Eingaben möglich");
182     jLbCopyright.setBounds(32861618316);
183     jLbCopyright.setText("(c)  R. Krell, www.r-krell.de");
184     jLbCopyright.setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
185     cp.add(jLbCopyright);
186     // Ende Komponenten
187     setResizable(false);
188     setVisible(true);
189   }
190 
191   // Anfang Methoden
192   public void jBtVoraussetzungen_ActionPerformed(ActionEvent evt) {
193     jTaAusgabe.append(db.zeigeVoraussetzungen()+"\n");
194   }
195 
196   public void jBtCreate_ActionPerformed(ActionEvent evt) {
197     jTaAusgabe.append(db.erzeugeDatenbank() +"\n");
198   }
199 
200   public void jBtUse_ActionPerformed(ActionEvent evt) {
201     jTaAusgabe.append(db.verwendeDatenbank() +"\n");
202   }
203 
204   public void jBtSelectAll_ActionPerformed(ActionEvent evt) {
205     jTaAusgabe.append(db.selectAll() +"\n");
206   }
207 
208   public void jBtOK_ActionPerformed(ActionEvent evt) {
209     String name = jTfName.getText();
210     int jahre = -1;
211     try
212     {
213       jahre = Integer.parseInt (jTfAlter.getText());
214     }
215     catch (Exception e1) { };
216     if (jahre < 0)
217     {
218       jTaAusgabe.append("Ungültiges Alter: Bitte positive Ganzzahl eingeben!\n");
219       return// beendet Methode
220     }
221     String knr = jTfKundenNr.getText();
222     if (knr==null || knr.equals(""))
223     {
224       jTaAusgabe.append(db.neuerKundeAuto(name,jahre)+"\n"); // automatische Kundennr
225     }
226     else
227     {
228       boolean okay = false;
229       int nr = 0;
230       try
231       {
232         nr = Integer.parseInt (jTfKundenNr.getText());
233         okay = true;
234       }
235       catch (Exception e1) {};
236       if (!okay)
237       {
238         jTaAusgabe.append("Ungültige Kundennummer: KdNr entweder ganz leer lassen oder eine Ganzzahl eingeben!\n");
239       }
240       else
241       {
242         jTaAusgabe.append(db.neuerKunde(nr, name, jahre)+"\n");  // mit vorgegebener Nummer
243       }
244     }
245   }
246 
247   public void jBtAbbrechen_ActionPerformed(ActionEvent evt) {
248     jTfKundenNr.setText("");
249     jTfName.setText("");
250     jTfAlter.setText("");
251   }
252 
253   public void jBtAusfuehren_ActionPerformed(ActionEvent evt) {
254     String ein = jTfSQLBefehl.getText();
255     if ((ein == null) || (ein.equals("")))
256     {
257       jTaAusgabe.append("Bitte erst einen SQL-Befehl in die Eingabezeile eintragen!\n");
258     }
259     else
260     {
261       jTaAusgabe.append(db.führeSQLBefehlAus(ein) +"\n");
262     }
263   }
264 
265   public void jBtVerwerfen_ActionPerformed(ActionEvent evt) {
266     jTfSQLBefehl.setText("");
267   }
268 
269   // Ende Methoden
270 
271   public static void main(String[] args) {
272     new DBJ_JOberflaeche("Demo: MySQL-Zugriff mit/aus Java  (www.r-krell.de)");
273   }
274

Soweit der Quelltext der Oberfläche. Einleitend gab es ein paar kurze Erläuterungen [direkt vor Beginn des Quelltextes in diesem Abschnitt 1)].

zum Seitenanfang / zum Seitenende

2) Das Aussehen der Oberfläche

Die vorstehend im Quelltext beschriebene Oberfläche präsentiert sich nach dem Start bzw. beim Ausführen des Java-Programms in der folgenden Form, wobei das untere große Ausgabefenster die Reaktionen auf die betätigten Schaltflächen protokolliert und zeigt, dass hier schon einige Tasten gedrückt wurden (nämlich "TestJDB neu erstellen", "Tabelle 'Kunde' zeigen", " O.K. " und nochmal "Tabelle 'Kunde' zeigen").

Das Programm in Aktion -- Blick auf die Oberfläche mit Beispielausgaben (Screenshot)

Die Programmierung für das, was beim Betätigen der Schaltfläche passiert, folgt in der nachfolgend ebenfalls vollständig vorgestellten Klasse DBJ_JFunktion.


zum Seitenanfang / zum Seitenende



Die Arbeitsklasse DBJ_JFunktion im Java-Quelltext



1) Die Methoden zeigeVoraussetzungen und sucheKontakt

Hier folgt der eigentlich spannende Teil, nämlich die Java-Befehle zum Arbeiten mit einer Datenbank. Alle nummerierten, weiß unterlegten Zeilen bilden zusammen die Klasse DBJ_JFunktion.
Zunächst folgt der Kopf der Klasse. Die Methode zeigeVoraussetzungen (folgende Zeilen 022 bis 033) wird aus der Oberfläche heraus aufgerufen, wenn dort die Taste [Voraussetzungen] gedrückt wird (siehe auch oben, Oberflächen-Zeile 193).

001 // Demo: Datenbankzugriff aus/mit Java
002 // 12.6.2010, R. Krell für IF12M
003 
004
 import java.sql.*;
005
 
006
 public class DBJ_JFunktion
007
  // Voraussetzungen:
008  // 1.
009  // MySQLConnector/J von http://dev.mysql.com/downloads herunter geladen
010  // und aus der heruntergeladenen Datei mysql-connector-java-5.1.12.zip
011  // das dort enthaltene Verzeichnis mysql-connector-java-5.1.12 irgendwohin
012  // gespeichert und im JavaEditor unter Fenster > Konfiguration > Interpreter >
013  // > Classpath-User den Pfad zu ;X:\Irgendwo\mysqlconnector\
014  // \mysql-connector-java-5.1.12-bin.jar eingetragen.
015  // 2.
016  // Außerdem muss Xampp gestartet sein und MySQL running!
017  
018
 {
019
   Connection con = null;
020
   String Fehler = "";
021
 
022
   public String zeigeVoraussetzungen()
023
   {
024
     String v = "Dieses Programm funktioniert nur, wenn:\n"
025
               +"1. auf Ihrem Computer MySQL installiert ist und läuft\n"
026
               +"   (weil Sie z.B. MySQL mit dem Xampp-Control-Panel gestartet haben)\n"
027
               +"2. zusätzlich zu Java der MySQL-Connector vorhanden ist und gefunden wird\n"
028
               +"   (mysql-connector-java-5.1.12-bin.jar wurde der jar-Datei dieses Programms\n"
029
               +"   beigefügt. Wenn Sie selbst programmieren bzw. den Quelltext kompilieren,\n"
030
               +"   müssen Sie den Connector in Ihre Java-Entwicklungsumgebung einbinden!)\n"
031
               +"(Mehr Info im Internet unter http://www.r-krell.de/if-db1.htm und ..db3.htm)\n";
032
     return (v);
033
   }
034
 
035
   private String sucheKontakt()
036
   {
037
     try
038
     {
039
       Class.forName("com.mysql.jdbc.Driver");
040
       con = DriverManager.getConnection
041
         ("jdbc:mysql://localhost/?user=root&password=");
042
       return ("Verbindung von Java zu MySQL erfolgreich erstellt.\n");
043
     }
044
     catch (Exception ex)
045
     {
046
       con = null;
047
       Fehler = "** Fehler beim Verbindungsaufbau von Java zu MySql:\n"+ex+"\n"
048
                +"Die Voraussetzungen für den Betrieb dieses Programms sind nicht erfüllt!\n\n";
049
       return (Fehler);
050
     }
051
   }
052

...


Während hier in den Zeilen 007 bis 016 und 022 bis 033 nur die Voraussetzungen für den Programmierer bzw. den Nutzer genannt werden, sind die Zeilen 039 ff beachtenswert:

Tatsächlich ist die Methode sucheKontakt (Zeilen 035 bis 051) hier als private deklariert und wird nur in den folgenden Methoden benutzt bzw. aus den folgenden Methoden heraus aufgerufen.

zum Seitenanfang / zum Seitenende

2) Die Methode erzeugeDatenbank

Die folgende Methode wird aufgerufen, wenn in der Oberfläche die Schaltfläche [TestJDB neu erstellen] gedrückt wird (vgl. Oberflächen-Zeile 197), um eine kleine Beispieldatenbank erstmals zu erstellen:

...
053   public String erzeugeDatenbank ()
054
   {
055
     String a = "";  // Ausgabe-String, der an die aufrufende Stelle (Oberfläche) zurück gegeben wird 
056     if (con == null) {
057       a = sucheKontakt();
058     }
059     String ausgabe = "Datenbank wurde eingerichtet, Kundentabelle mit 3 Kunden gefüllt.\n";
060     try
061     {
062       Statement stmt = con.createStatement(); // ein Statement (=Java-Behälter für das
063        // Verschicken eines SQL-Befehls) für die/über die Datenbank-Verbindung con wird erzeugt
064       String sqlBefehl = "create database TestJDB;"// String mit einer SQL-Anweisung
065       int betroffeneZeilen = stmt.executeUpdate(sqlBefehl); // schickt den String mit
066        // der SQL-Anweisung zur Datenbank und erhält die Anzahl der betroffenen Zeilen zurück.
067        // "executeUpdate" für DCL-, DDL- und DML-Befehle [Datenbankkontrolle, Datenbankdefinition
068        // und Datenbankmanipulation] -- im Prinzip für alles außer für  select-Abfragen]
069       a = a + " > "+sqlBefehl+" ["+betroffeneZeilen+"]\n"// vom Befehl zurückgegebene Zahl in Ausgabe-String 
070        
071       sqlBefehl = "use TestJDB;"// String mit einer SQL-Anweisung
072       betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
073       a = a + " > " + sqlBefehl+" ["+betroffeneZeilen + "]\n";
074       
075       sqlBefehl = "create table kunde (kundennr int primary key auto_increment, name varchar(20), jahre int);";
076       betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
077       a = a + " > " + sqlBefehl+" ["+betroffeneZeilen+"]\n";
078       
079       sqlBefehl = "insert into kunde (name, jahre)"
080
                  +" values ('Meier', 17), ('Lehmann', 19), ('Schulze', 18);";
081       betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
082       a = a + " > " + sqlBefehl+" ["+betroffeneZeilen+"]\n";
083       ausgabe = a + ausgabe;
084     }
085     catch (Exception ex)
086     {
087       ausgabe = ("** Fehler beim Versuch, die Datenbank erstmals einzurichten:\n"+ex+"\n"); // Fehlermeldung
088     }
089     return (ausgabe);
090   }
091
...

In der vorstehenden Methode erzeugeDatenbank werden aus Java heraus alle SQL-Befehle an den MySQL-Server geschickt, die nötig sind, um dort die Datenbank TestJDB zu erzeugen (Zeile 064), sie für künftige Befehle auszuwählen (Zeile 071), darin die Tabelle Kunde mit drei Attributen/Spalten und (ggf. automatisch vergebenem) Primärschlüssel KundenNr zu erzeugen (Zeile 075) und diese Tabelle dann mit drei Datensätzen zu füllen (Zeilen 079/080), wobei die Kundennr automatisch vergeben wird.

Damit das klappt, wird aber zunächst -- bei noch nicht vorhandene Verbindung con == null -- die in die private Methode sucheKontakt ausgelagerte Datenbankverbindung hergestellt (Zeilen 056 bis 058 bzw. vorangehender Abschnitt 1) für den Text von sucheKontakt).

Im vorstehenden Quelltext bin ich extra etwas umständlich vorgegangen, um die Übersichtlichkeit zu fördern. Zunächst wird einmal im Rahmen der Datenbankverbindung con ein Statement-Behälter stmt erzeugt (Zeile 062), der anschließend verschiedene SQL-Befehle zur Ausführung übergeben bekommt (Zeilen 065, 072, 076 und 081) und dabei jeweils die von MySQL gelieferte Antwort an die (Ganzzahl-)Variable betroffeneZeilen als Funktionswert bzw. Ergebnis zurück gibt. executeUpdate eignet sich nämlich nur für alle diejenigen SQL-Befehle, bei denen MySQL nur eine einzige Ganzzahl, nämlich die Anzahl der von der Befehlsausführung betroffenen Zeilen zurück gibt. Das sind aber nicht nur Update-, sondern (wie man hier sieht) auch Create-, Use- und viele andere Manipulationsbefehle! Den jeweiligen SQL-Befehl habe ich immer erst in die Text- bzw. String-Variable sqlBefehl geschrieben und dann diese Variable als Parameter an executeUpdate übergeben. Das gelieferte Ergebnis habe ich immer erst der Variable betroffeneZeilen zuweisen lassen, und dann diese Variable zusammen mit dem Text des ausgeführten Befehls (aus sqlBefehl) meinem Ausgabestring a hinzugefügt, der alle Meldungen und Ergebnisse für die Ausgabe in der Oberfläche sammelt (Anzeige dort im Textfeld jTaAusgabe).

Kürzer hätten jeweils drei Zeilen immer zu einer zusammengefasst werden können, z.B. statt 071 bis 073 kurz (aber weniger übersichtlich):
   
a = a + " > use TestJDB;" + stmt.executeUpdate ("use TestJDB");

In Zeile 075 wurde als Attributname übrigens extra jahre (und nicht etwa alter) verwendet: Sonst wären fast immer Anführungszeichen um den Attributnamen nötig, damit MySQL den Spaltennamen "Alter" vom SQL-Befehl alter für Änderungen in der Tabellenstruktur unterscheiden kann.

zum Seitenanfang / zum Seitenende

3) Die Methode verwendeDatenbank

Wurde die Datenbank mit der Kundentabelle schon in einer früheren Sitzung erzeugt, kann sie weiter verwendet werden -- dazu muss in der Oberfläche nur der Knopf [TestJDB benutzen] gedrückt werden (siehe Oberflächen-Zeile 201):

...
092   public String verwendeDatenbank()
093   {
094     String a = "";
095     if (con == null) {
096       a = sucheKontakt();
097     }
098     try
099     {
100       Statement stmt = con.createStatement(); // ein Statement (=Java-Behälter für SQL)
101       String sqlBefehl = "use TestJDB"// String mit einer SQL-Anweisung
102       int betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
103       a = a + " > " + sqlBefehl+" ["+betroffeneZeilen+"]\n";
104     }
105     catch (Exception ex)
106     {
107       a = a + "** Fehler -- use-Befehl gelang nicht: "+ex;
108     }
109     return (a);
110   }
111
...

Im Wesentlichen wird in der vorstehenden Methode nur der Kontakt zur Datenbank aufgebaut (sofern noch nicht geschehen; Zeilen 095 bis 097) und dann -- wie in 062 und 071 bis 073 -- der use-Befehl ausgeführt und die Zahl der betroffenen Zeilen zur Kontrolle über den Ausgabestring a an die aufrufende Stelle (nämlich die Oberfläche, dort Oberflächen-Zeile 201) gemeldet.

zum Seitenanfang / zum Seitenende

4) Die Methoden neuerKundeAuto und neuerKunde

Jetzt folgt die Methode, die die Arbeit erledigt, falls in die Eingabefelder (Textfelder) der Oberfläche die Daten eines neuen Kunden eingegeben wurden und dort die Schaltfläche [ O.K. ] zum Aufnehmen des neuen Kunden gedrückt wird. Der Aufruf erfolgt aus der Oberfläche (s.o.), Oberflächen-Zeilen 208 bis 245, bzw. insbesondere in Oberflächen-Zeile 224.



...
112   public String neuerKundeAuto (String name, int alter)  // Kunde ohne Nr. erhält automatisch eine!
113   {
114     String a;
115     String ausgabe = "Kunde wurde aufgenommen.\n";
116     try
117     {
118       Statement stmt = con.createStatement();
119       int betroffeneZeilen;
120       String sqlBefehl;
121       sqlBefehl = "insert into kunde (name, jahre)"
122
                   +" values ('"+name+"',"+alter+")";
123       betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
124       a = " > "+sqlBefehl+" ["+betroffeneZeilen+"]\n";
125       ausgabe = a + ausgabe;
126     }
127     catch (Exception ex)
128     {
129       ausgabe = ("** Fehler bei der Aufnahme von ('"+name+"', "+alter+"):\n"+ex+"\n"); // Fehlermeldung
130     }
131     return (ausgabe);
132   }
133
...

Die vorstehenden Methode wird benutzt, wenn das Eingabefeld für die Kundennummer frei gelassen wurde und deshalb die Kundennummer von MySQL automatisch vergeben werden muss (dies geht, da in Zeile 075 auto_increment angegeben war). Das Einfügen von Werten erfolgt dann nur für die Spalten/Attribute name und jahre wie man in Zeile 121 sieht. Auch der insert-Befehl gibt wie alle bisher verwendeten SQL-Anweisungen nur die Anzahl der betroffenen Zeilen zurück, wird also mit executeUpdate von Java aus an die Datenbank übermittelt. Der Quelltext in den Zeilen 120 bis 124 könnte -- wie schon oben bei 071 bis 073 beschrieben -- zu einer Zeile verkürzt werden.

Hat der Benutzer hingegen eine Kundennummer ins entsprechende Eingabefeld eingetippt und wurde diese von der Oberfläche als Ganzzahl erkannt und verwandelt, dann wird die folgende Variante der Methode aufgerufen (aus der Oberflächen-Zeile 242 heraus):

...
134   public String neuerKunde (int kdnr, String name, int alter) // Kunde mit kdnr
135   {
136     String a;
137     String ausgabe = "Kunde wurde aufgenommen.\n";
138     try
139     {
140       Statement stmt = con.createStatement(); // ein Statement (=Java-Behälter für SQL)
141       int betroffeneZeilen;
142       String sqlBefehl;
143       sqlBefehl = "insert into kunde (kundennr, name, jahre)"
144
                   +" values ("+kdnr+",'"+name+"',"+alter+")";
145       betroffeneZeilen = stmt.executeUpdate(sqlBefehl);
146       a = " > "+sqlBefehl+" ["+betroffeneZeilen+"]\n";
147       ausgabe = a + ausgabe;
148     }
149     catch (Exception ex)
150     {
151       ausgabe = ("** Fehler bei der Aufnahme von ("+kdnr+", '"+name+"', "+alter+"):\n"+ex+"\n"); // Fehlermeldung
152     }
153     return (ausgabe);
154   }
155   
...

Bei der Ausführung kommt es natürlich zu einem Fehler (der als Ausgabe im Oberflächenfenster erscheint und nicht zum Programmabbruch führt), wenn der Benutzer eine bereits verwendete Kundennummer eingegeben hat, da in Zeile 075 die Kundennummer als Primärschlüssel gekennzeichnet wurde und daher eindeutig ein muss.

zum Seitenanfang / zum Seitenende

5) Die Methoden aufgefüllt, abfrageMit und abfrageOhne

Bisher wurden nur SQL-Befehle (mit executeUpdate) an die Datenbank weiter gegeben, die als Ergebnis bzw. Funktionswert nur die Anzahl der betroffenen Zeilen liefern. Will man hingegen eine Select-Abfrage ausführen, erwartet man als Rückgabe eine Ergebnistabelle. Leider ist die Datenbank-Anbindung in Java nicht ganz so komfortabel wie in Delphi: Dort kann man mit TTable, TDataSource und DBGrid Komponenten verwenden, die Datenbanktabellen praktisch automatisch anzeigen und sogar eine Änderung der Datenbanktabelle durch Änderungen in der Oberfläche ermöglichen. Natürlich ist in Java beispielsweise die Verwendung eines jTable-Objekts möglich (in diesem Fall würde sich empfehlen, das jTable-Objekt der Oberfläche als Parameter an die folgenden Methoden zu übergeben, damit es dort eingerichtet und gefüllt werden kann). Allerdings muss der Programmierer durch eigenen Programmtext aus der Rückgabe des executeQuery-Befehls die Zahl der Spalten und Zeilen der Tabelle ermitteln, das jTable-Objekt entsprechend erzeugen bzw. abändern und den einzelnen Tabellenfeldern dann auch einzeln (bzw. in geeigneten Schleifen) die entsprechenden Werte der Antworttabelle zuweisen. Dann stehen dem Benutzer aber auch automatisch viele übliche Tabellendarstellungsfunktionen zur Verfügung, beispielsweise werden die Zeilen beim Klick auf eine Spaltenüberschrift nach den Werten in dieser Spalte sortiert. Wenn man aber will, dass Änderungen des Benutzers an den dargestellten Tabellenwerten umgekehrt auch wieder in die Datenbank übernommen werden, ist das mühsame Schreiben von viel weiterem Programmtext nötig. Im Internet findet man entsprechende Foren-Beiträge. Mag sein, dass manche Entwicklungsumgebungen die Schwächen Javas ausgleichen und vorbereiteten Quelltext für entsprechende Methoden liefern -- der hier verwendete Javaeditor tut es jedenfalls nicht. Und da dieser Beitrag eher die grundsätzlichen Möglichkeiten aufzeigen will, als wichtige Befehle durch Oberflächenkosmetik zu verschleiern, habe ich mich entschlossen, die Antworttabellen mit ein paar zusätzlichen Strichen im TextArea-Feld auszugeben, in dem schon die normale Programmausgabe erfolgt -- und gar kein jTable-Objekt zu verwenden. Neue Spalten könnten durch Tabulatorsprünge angesteuert werden; unterscheiden sich aber die Werte so stark, dass ihre Längen mehrere Tabulatormarken (im Abstand von 8 Zeichen) Unterschied haben, ist das Verwenden einer passenden Anzahl von Leerzeichen (bei Schrift mit fester gleicher Buchstabenbreite) sinnvoller. Die konstante Buchstabenbreite wurde oben in der Oberfläche in der Oberflächen-Zeile 180 eingestellt ("monospaced"), eine Methode zum Abschneiden des Texts nach der bzw. Auffüllen des Texts mit anschließenden Leerzeichen bis zur angegebenen Zahl von Zeichen ist nachstehend genannt:


...
156   private String aufgefüllt (String text, int zahl)
157   {
158     text = (text+"                                                                         ")
159              .substring(0, zahl-1);
160     return (text+"|");
161   }
162 
...

Die Methode aufgefüllt fügt außerdem am Ende des Ausgabetexts einen senkrechten Strich als Spaltenbegrenzung an. Sie wird bei der Ergebnisausgabe in der nun folgenden Methode abfrageMit verwendet. Auch die folgende Methode ist private deklariert, da sie nicht direkt aus der Oberfläche, sondern nur weiter unten aus der Funktions-Methode führeSQLBefehlAus (Zeilen 226 ff) aufgerufen wird. Sie übernimmt aber die Weiterleitung eines Select-Befehls an die Datenbank und interpretiert die Rückgabe bzw. bereitet die Rückgabe so auf, dass ein mehrzeiliger Text mit der Darstellung einer Tabelle entsteht. Um die Möglichkeit zu zeigen, wurde als Kopf jeder Spalte immer die Spaltenüberschrift (Attribut-Name), der Attributtyp von MySQL und die Spaltenbreite (als maximale Anzahl der Zeichen) 3-zeilig notiert, bevor -- getrennt durch eine gestrichelte Linie -- darunter die Tabelleneinträge folgen (wie auch im Bild weiter oben auf dieser Seite [Kapitel Oberfläche, Abschnitt 2) "Das Aussehen der Oberfläche"] zu sehen ist).

163   private String abfrageMit (String sql)  // für Select-Abfrage o.ä. mit komplexem Tabellen-Ergebnis
164   {
165     String ausgabe = " > "+sql+":\n";
166     try
167     {
168       Statement stmt = con.createStatement(); // ein Statement
169       ResultSet result = stmt.executeQuery(sql);
170       ResultSetMetaData rsmd = result.getMetaData();
171       int spaltenzahl = rsmd.getColumnCount();
172 
173       for (int i=1; i<=spaltenzahl; i++)
174       {
175         ausgabe = ausgabe + aufgefüllt(rsmd.getColumnName(i), rsmd.getColumnDisplaySize(i));
176       }
177       ausgabe = ausgabe+"\n";
178       for (int i=1; i<=spaltenzahl; i++)
179       {
180         ausgabe = ausgabe + aufgefüllt(rsmd.getColumnTypeName(i), rsmd.getColumnDisplaySize(i));
181       }
182       ausgabe = ausgabe+"\n";
183       for (int i=1; i<=spaltenzahl; i++)
184       {
185         ausgabe = ausgabe + aufgefüllt("("+rsmd.getColumnDisplaySize(i)+")", rsmd.getColumnDisplaySize(i));
186       }   // Spaltenbreite
187       ausgabe = ausgabe+"\n";
188 
189       for (int i=1; i<=spaltenzahl; i++)
190       {
191         ausgabe = ausgabe + aufgefüllt("------------------------------------------------------------", rsmd.getColumnDisplaySize(i));
192       }
193       ausgabe = ausgabe+"\n";
194       while(result.next()) // solange das resultSet noch weitere Zeilen enthält
195       {
196         for (int i=1; i<=spaltenzahl; i++)
197         {
198           ausgabe = ausgabe + aufgefüllt(result.getString(i), rsmd.getColumnDisplaySize(i));
199         }
200         ausgabe = ausgabe+"\n";
201       }
202     }
203     catch (Exception ex)
204     {
205       ausgabe = ("** Fehler bei der Abfrage '"+sql+"':\n"+ex+"\n"); // Fehlermeldung
206     }
207     return (ausgabe);
208   }
209
...

Neu ist in der vorstehenden Methode:

Natürlich hilft -- wie immer bei Java -- ein Blick in die API der Java-Dokumentation, um die Möglichkeiten der Bibliotheksklassen und ihre Attribute und Methoden kennen zu lernen (s.u.).



Während die vorstehende Methode Select-Befehle mit umfangreicher Ausgabe ausführt, ist die folgende Methode für SQL-Befehle ohne Tabellen-Rückgabe, sondern mit einfachem Zahlergebnis gedacht:

...
210   private String abfrageOhne (String sql)  // für SQL-Befehle ohne umfangreiche Rückgabe, sondern mit einfachem Ganzzahl-Ergebnis
211   {
212     String ausgabe = "";
213     try
214     {
215       Statement stmt = con.createStatement(); // ein Statement
216       int betroffeneZeilen = stmt.executeUpdate(sql);
217       ausgabe = " > "+sql+" ["+betroffeneZeilen+"]\n";
218     }
219     catch (Exception ex)
220     {
221       ausgabe = ("** Fehler bei der Abfrage '"+sql+"':\n"+ex+"\n"); // Fehlermeldung
222     }
223     return (ausgabe);
224   }
225
...

Wenn das Ergebnis nur aus einer Zahl besteht, und nicht aus vielen Werten erst ein formatierter Text erstellt werden muss, ist die vorstehende Methode abfrageOhne natürlich viel einfacher als die davor aufgeführte Methode abfrageMit und funktioniert in Zeile 216 mit der aus den Abschnitten 1) bis 4) schon wohl bekannten executeUpdate-Methode des Statements stmt.

zum Seitenanfang / zum Seitenende

6) Die Methode führeSQLBefehlAus

Je nachdem, ob der Benutzer in das für SQL-Befehle vorgesehene Eingabefeld der Oberfläche nun einen Select- oder einen anderen SQL-Befehl eingegebenen hat, entscheidet nach dem Druck auf [Ausführen] die folgende Methode führeSQLBefehlAus in Zeile 228, welche der beiden vorstehenden privaten Methoden sie nutzt. Die Oberfläche ruft diese Methode in der Oberflächen-Zeile 261 auf:

...
226   public String führeSQLBefehlAus (String sqlBefehl)
227   {
228     if (sqlBefehl.substring(0,6).compareToIgnoreCase("select")==0)
229     {
230       return (abfrageMit (sqlBefehl));
231     }
232     else
233     {
234       return (abfrageOhne (sqlBefehl));
235     }
236   }
237
...

Weil evtl. führende Leerzeichen nicht vor der Kontrolle entfernt werden, kann damit versucht werden, einen Select-Befehl durch den Java-executeUpdate-Befehl in abfrageOhne ausführen zu lassen, was natürlich zu einer Java-Exception führt.

zum Seitenanfang / zum Seitenende

7) Die Methode selectAll

Die vorletzte Methode in der Klasse wird schließlich angestoßen, wenn sich der Benutzer mit [Tabelle 'Kunde' zeigen] die Tabelle Kunde zeigen lässt (vgl. Oberflächen-Zeile 205). Sie startet einfach eine entsprechende Select-Abfrage über die im Abschnitt 5) genannte Methode abfrageMit (Zeilen 163 bis 208):

...
238   public String selectAll()
239   {
240     return (abfrageMit ("select * from kunde;"));
241   }
242
...

zum Seitenanfang / zum Seitenende

8) Die Methode beendeKontakt

Und schließlich noch die Methode beendeKontakt, die das grundsätzliche Gegenstück zu sucheKontakt (Zeilen 035 bis 051) ist, aber hier nie wirklich aufgerufen/verwendet wird:

...
243   public void beendeKontakt()
244   {
245     if(con != null)
246     {
247       try
248       {
249         con.close(); // Schließt Verbindung
250       }
251       catch (Exception ex)
252       {
253         System.out.println("Verbindung kann nicht getrennt werden: "+ex);
254       }
255     }
256   }
257 } // Ende der Klasse DBJ_JFunktion



zum Seitenanfang / zum Seitenende

Der Programmstart



Beim Start des Programms zeigt sich die Oberfläche (da die in der Oberflächen-Klasse enthaltene main-Methode die Oberfläche startet, die ihrerseits ein Objekt der Klasse DBJ_JFunktion erzeugt und verwendet -- siehe Quelltext der Oberfläche, Oberflächen-Zeilen 271 bis 273 sowie Oberflächen-Zeile 040).

Bildschirmansicht Programmoberfläche mit XAMPP-Control-Panel und Firewall_Warnung

Bevor irgendwelche Knöpfe (außer der Schaltfläche "Voraussetzungen") gedrückt werden, muss MySQL z.B. über das XAMPP-Control-Panel (hier in den Vordergrund geholt) gestartet sein. Nur wenn der Server läuft, kann der in Java geschriebene Datenbank-Client Kontakt zu MySQL aufnehmen! Wird dann "TestJDB neu erstellen" oder "TestJDB benutzen" gedrückt, also die Verbindung zur Datenbank aufgenommen, merkt dies eine eventuell installierte Firewall und der Vorgang muss erlaubt werden.

Eine Verwendung des Programms als (J)Applet ist übrigens nicht möglich: Die Sicherheitseinstellungen von Java verbieten, dass ein Applet aus dem Internet Dateien auf dem lokalen Rechner liest oder Kontakt zur lokalen Datenbank aufnimmt. Aber der Webstart (mit erweiterten Rechten) oder der Download sind möglich:

Wenn die Java-JRE installiert ist und MySQL läuft, können Sie das Programm jetzt sofort ausführen:

Hier klicken zum Webstart des Datenbank-Programms

Danach Öffnen von Datenbank_J.jnlp [mit Java(TM) Webstart Launcher (Standard)] wählen/bestätigen
und bei evtl. Sicherheitswarnung vor der Ausführung von DBJ_JStart das Risiko akzeptieren und OK drücken.

Wenn Sie außerdem gefragt werden, ob Sie eine Desktop- und eine Startmenüverknüpfung anlegen wollen,
sollten Sie zustimmen, wenn Sie das Programm auch nach Verlassen dieser Webseite nochmal ausprobieren wollen.

Wird nach dem Klick Datenbank_J.jnlp herunter geladen oder werden Sie gefragt, womit Sie Datenbank_J.jnlp öffnen wollen
oder ob/wohin Sie die Datei speichern wollen, haben Sie entweder kein Java installiert oder ihr Browser (z.B. Opera) unterstützt keinen Webstart.
Im letzten Fall empfiehlt sich nachfolgend der Download der .jar-Datei:

Sie können das Datenbankprogramm auch als ausführbare Java-Datei herunter laden und später lokal auf Ihrem Rechner starten (Java-Umgebung JRE und laufender MySQL-Server vorausgesetzt):

Datenbank_per_Java(r-krell.de).jar (756 kB)

Die Datei muss auf dem eigenen Rechner gespeichert (nicht geöffnet und nicht entpackt) werden und lässt sich dann dort ausführen. Bei installiertem Java 1.6 oder höher reicht zum Start ein Klick auf den Namen der gespeicherten Datei. Enthalten ist das hier im Quelltext gezeigte Programm in kompilierter Form für Anschauungs-, Lehr- oder private Übungszwecke, ohne Haftung und ohne Gewährleistung. Die Verwendung meiner jar-Datei zu kommerziellen Zwecken, der Einbau herunter geladener Teile in eigene Programme usw. ist entsprechend dem Urheberrecht verboten!

Ändert man im Quelltext von DBJ_JFunktion in der Zeile 041 die Adresse der Datenbank von localhost in die IP-Adresse eines anderen Rechners, auf dem MySQL läuft, so sollte damit -- wie oben im Abschnitt 1) bei den Anmerkungen zur Zeile 040 bereits erwähnt -- auch der Kontakt zu einer Datenbank im Netz möglich sein; allerdings habe ich das noch nicht ausprobiert. Gleiches müsste übrigens auch für den MySQL Query Browser gelten, wenn im folgenden Kapitel dort im Feld 'Server Host:' statt localhost eine IP-Adresse eingetragen wird!


zum Seitenanfang / zum Seitenende

Alternativer Zugriff auf die gleiche Datenbank
zum Beispiel mit dem MySQL Query Browser



Wie oben schon im Eingangskapitel "Datenbanken und Java.." im Abschnitt 2) "Datenbankformate als gute Wahl bei allen komplexen Speicherungen" erwähnt, besteht ein großer Vorteil bei der Speicherung von Daten in Datenbanken darin, dass man nicht nur mit einem bestimmten Programm, sondern aus vielen Anwendungen auf die Daten zugreifen kann.

Beispielsweise kann zusätzlich zum vorgestellten Java-Programm der von meinen ersten beiden Datenbank-Seiten bekannte "MySQL Query Browser" gestartet werden und ebenfalls auf die durch das hier vorgestellte Java-Programm in MySQL erzeugte Beispieldatenbank TestJDB zugreifen und sie auch verändern!

Zunächst muss man sich auch mit diesem Client beim MySQL-Server (der natürlich weiterhin laufen muss) anmelden:

Bildschirmansicht: XAMPP-Control-Panel und Start des MySQL-Query-Browsers

Nach "Ignorieren" (weil kein Standardardschema ausgewählt wurde) öffnet sich schließlich die Oberfläche des Query-Browsers (wie in den Teilen 1 und 2 meiner Webseiten über Datenbanken bereits ausführlicher beschrieben) und man kann dort beliebige SQL-Befehle eintippen und ausführen, um sich unsere Datenbank bzw. ihre Tabelle(n) anzusehen, abzufragen oder um sie zu manipulieren:
Bildschirmansicht: MySQL-Query-Browser mit SQL-Eingaben zur Anzeige der Tabelle Kunde

So kann man schön die vielfache und damit zukunftssichere Verwendbarkeit des eigenen Datenbestands sehen!


zum Seitenanfang / zum Seitenende

Die API-Spezifikation der Java-Dokumentation



Wer weitere Informationen sucht, wie man aus Java mit Datenbanken kommunizieren kann, findet Hilfe und Tipps in Büchern, im Internet, aber nicht zuletzt auch in der Java-Dokumentation (API = Application Programming Interface = Schnittstelle für die Programmierung von Anwendungen). Wurde die getrennt herunter zu ladende Java-Dokumentation installiert [vgl. meine Seite "Informatik mit Java, Teil a)"] und der Pfad dem Javaeditor mitgeteilt [ebenfalls Teil a), "Installation und Einrichten des Javaeditors", dann dort weiter zu (3)], kann die Hilfe bequem angesehen werden. Befindet sich der Kursor in einem Klassennnamen (im Beispiel stand die Schreibmarke des Javaeditors im Wort "ResultSetMetaData" aus Zeile 170 von DBJ_JFunktion), so reicht der Klick auf F1, um die entsprechende Seite der Dokumentation zu öffnen. Die Java-Dokumentation ist auch online auf http://java.sun.com/javase/6/docs/api/ zu finden (Stand Anfang August 2010; wieweit sich durch die Übernahme von Sun durch Oracle auch hier bald URLs ändern, bleibt abzuwarten. Einige Leitseiten sind bereits verändert, so findet sich z.B. die Übersicht über die Dokumentationen der verschiedenen Java-Versionen schon jetzt nicht mehr unter www.java.sun..., sondern auf http://www.oracle.com/technetwork/java/javase/documentation/api-jsp-136079.html).

Bildschirmansicht Java-Dokumentation (API) im Javaeditor

Insofern ist eine Erweiterung der hier gezeigten Grundlagen bzw. eine Anpassung des vorgestellten Programms an eigene Wünsche sicher leicht möglich...


zurück zur Informatik-Hauptseite

zur vorangehenden Seite: Datenbanken, Teil 1
zur vorangehenden Seite: Datenbanken, Teil 2


zum Anfang dieser Seite
Willkommen/Übersicht  -  Was ist neu?  -  Software  -  Mathematik  -  Physik  -  Informatik  -   Schule: Lessing-Gymnasium und -Berufskolleg  -  Fotovoltaik  -  & mehr  -  Kontakt: e-Mail,  News-Abo, Gästebuch, Impressum  -  Grußkarten, site map, Download und Suche

Diese Seite ist Teil des Webangebots http://www.r-krell.de. Sie können diese Seite per e-Mail weiter empfehlen (tell a friend).