> Inhalt: Einführung in das Programmieren mit Java > Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) 

Tutorial:
Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) – SQL-Kommandos ausführen

* Bitte beachten Sie die Hinweise und Bestimmungen bezüglich Urheberrecht, Haftungsausschluß und geschützte Marken oder Warenzeichen die für dieses Web-Dokument und möglicherweise auch für 'verlinkte' Dokumente gelten.

  • Der Betreiber dieser Web-Site (www.javascout.biz) ist nicht verantwortlich für den Inhalt von Web-Sites, die innerhalb dieses Web-Dokumentes oder anderer Dokumente von www.javascout.biz verlinkt sind.

  • Wenn dieses Web-Dokument oder andere Dokumente dieser Web-Site (www.javascout.biz) Rechte von Ihnen verletzen, oder sie glauben, daß Rechte Anderer (Dritter Personen) dadurch verletzt werden, informieren Sie bitte den Betreiber dieser Web-Site.
    Eine E-Mail können Sie ganz einfach durch anklicken des Symbols oder Textes im Frame rechts oben senden.

Dieses Dokument drucken.

 Letzte Bearbeitung dieses  Dokuments:
2008-02-14



Voraussetzungen für das Verständnis dieses Dokuments:

Grundkenntnisse in der Programmierung von Java (Klassen, Methoden, Schleifen) oder anderer Objekt-Orientierter Programmiersprachen (z.B. C++, Modula-2, Pascal).

Ungefährer Zeitbedarf zum Durcharbeiten dieses Dokuments:

Arbeitszeit:
Ca.
.

Dieses Dokument zeigt, wie die SQL-Kommandos aus einer sequentiellen Datei gelesen werden und diese Kommandos an die Datenbank weitergeleitet werden.
Zum Verfolgen des Fortschritts der Verarbeitung wird vorgestellt, wie eine Klasse als parallel laufender 'Thread' (Prozeß) entworfen wird.
Das 'parallele' Durchführen der Verarbeitung bewirkt, daß die ausgeführten SQL-Kommandos und eventuelle Fehlermeldungen sofort auf der Benutzeroberfläche (GUI) angezeigt werden und nicht erst dann, wenn die Verarbeitung abgeschlossen ist.

Inhaltsverzeichnis:

Vorigerer Schritt: XML-Struktur lesen 

Vorbemerkung und Funktion des Codes 
Vorbedingungen 
Klasse
DB_Load__Thread eröffnen 
Vorläufiger Code in der Klasse
DB_Load__Thread 
Vorläufiger zusätzlicher Code in der Klasse
DB_Load__ActionHandler 
Zwischen-Test
 
Zusätzlicher Code 
* Import in der Klasse
DB_Load__Thread 
* Globale Variablen und 'Constructor' in der Klasse
DB_Load__Thread 
* Start des Thread in der Methode
processDBLoad(. . .) / Klasse DB_Load__ActionHandler 
* Code zum Einlesen der Datei mit den SQL-Kommandos / Klasse
DB_Load__Thread 
* Code für die Methode
processDBOperation(. . .) zum Ausführen der SQL-Kommandos / Klasse DB_Load__Thread 
Datei mit den SQL-Kommandos erstellen 
Gesamter Code beim Ende dieses Schritts 
* Klasse
DB_Load 
* Klasse
DB_Load__ActionHandler 
* Klasse
DB_Load__Thread 
Test
 
Weitere Schritte und verwandte Dokumentation 

Die Einführung in die wichtigsten Felder als Basis für die Entwicklung kommerzieller Anwendungen mit Java ist jetzt abgeschlossen.

Nächster Schritt: Meldungen drucken 
Dieser Schritt stellt eine einfache Möglichkeit für den Ausdruck vor.
Seit der ersten Version dieses Dokuments wurde die Möglichkeit zum Drucken in Java wesentlich verbessert – Beispiele und Anleitung für die Möglichkeiten zum Drucken ab Java Version 1.4 folgen demnächst.

Eine Anleitung, wie eine JAR- (Java-ARchiv-) Datei erstellt wird und wie das entwickelte Programm außerhalb von Eclipse ausgeführt wird, finden Sie im Schritt Packen in JAR-Datei .

Vorbemerkung und Funktion des Codes

In diesem Dokument wird der Code so erweitert, daß die gewählte Datei mit den SQL-Kommandos geöffnet wird, Zeile für Zeile (jede Zeile enthält ein SQL-Kommando) aus der Datei gelesen wird und das SQL-Kommando an das Datenbanksystem weitergeleitet wird.

Diese Verarbeitung geschieht in einem parallel laufenden Prozeß damit die ausgeführten SQL-Kommandos und eventuelle Fehlermeldungen sofort auf der Benutzeroberfläche (GUI) angezeigt werden können.

zum Inhaltsverzeichnis

Vorbedingungen

zum Inhaltsverzeichnis

Klasse DB_Load__Thread eröffnen

Das Eröffnen der neuen Klasse wird nur in Stichworten und ohne Abbildungen dokumentiert.
Wenn Sie sich unsicher sind, sehen Sie bitte unter
Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) – Einrichten von Project und Class > Class DB_Load eröffnen nach, wie eine Klasse eröffnet wird.

Package: js_intro02.client
Name: DB_Load__Thread
[ ] public static void main(String[] args)   (nicht markiert)
[ ] Constructors from superclass   (nicht markiert)
[ ] Inherited abstract methods   (nicht markiert)

zum Inhaltsverzeichnis

Vorläufiger Code in der Klasse DB_Load__Thread

Um schnell den Effekt eines parallel laufenden Prozesses zeigen zu können, wird zuerst ein einfacher Code implementiert der die Zahlen von 1 bis 20 mit einer Sekunde Pause dazwischen auf der GUI anzeigt.

Jetzt wird nur der Code mit den enthaltenen Kommentaren gelistet; die detaillierte Beschreibung erfolgt dann beim endgültigen Code für das Verarbeiten der SQL-Kommandos.

package js_intro02.client;
/**
 *
 * @author kurt@javascout.biz
 * @date 2008-02-14
 *
 * @description
 *  Klasse mit einem 'Thread', der die Datei mit den SQL-Kommandos öffnet,
 *  diese Datei Zeile für Zeile liest (jede Zeile enthält ein SQL-Kommando),
 *  diese SQL-Kommandos an die Datenbank übergibt und
 *  das SQL-Kommando und eventuelle Fehlermeldungen auf der GUI ausgibt.
 *
 * @change-log
 * when         who               why
 * --------------------------------------------------------
 *
 */

public class DB_Load__Thread extends Thread {
/*
 * Variable, die auf die Klasse mit der GUI verweist.
 * Damit kann periodisch die jeweilige Zahl auf der GUI angezeigt werden. */
    DB_Load frmCallingFrame;
/* 
 * 'Constructor' der Klasse.
 * Der als Parameter übergebene Wert wird als 'final' definiert.
 * Das bedeutet, daß sich der Wert des Parameters nicht ändert während der 'Thread'
 * ausgeführt wird und mit 'final' wird die Performance verbessert. */
      public DB_Load__Thread(final DB_Load parmCallingFrame) {
/*
 * Der als Parameter übergebene Wert wird in der Variablen dieser Klasse gespeichert. */
      frmCallingFrame = parmCallingFrame;
    }
/* 
 * Die Methode 'run' wird automatisch gestarted nachdem das Objekt 'konstruiert' wurde. */
    public void run() {
/*
 * Eine Klasse mit der Superklasse 'Thread' braucht eine Fehlerbehandlung
 * für den Fall, daß die Ausführung von 'außen', d.h. durch die aufrufende Methode,
 * unterbrochen wurde. Deswegen die try/catch-Logik. */
      
try {
/*
 * Vorläufiger Code für die Klasse:
 * Hochzählen von 1 bis 20 und anzeigen des Wertes auf der GUI
 * mit 1 Sekunde Pause dazwischen. */
        
for (int i = 0; i<= 20; i++) {
/* Anzeigen der Zahl auf der GUI. */

          frmCallingFrame.get_txt_Report().append(
              
"Durchlauf in DB_Load__Thread: " + Integer.toString(i) + "\n");
/* Eine Sekunde warten bis die Schleife fortgesetzt wird. */
          sleep(1000);
        }
      }
      
catch (Exception e) {
/*
 * Unerwarteted Ende des Threads; Fehlermeldung auf der GUI ausgeben. */
        
frmCallingFrame.get_txt_Report().append(
            
"Unerwartetes Ende von DB_Load__Thread: " + e.toString() + "\n");
      }
    }
}

zum Inhaltsverzeichnis

Vorläufiger zusätzlicher Code in der Klasse DB_Load__ActionHandler

Der zusätzliche Code beschränkt sich darauf, in der Methode processDBLoad(. . .) ein Objekt der Klasse DB_Load__Thread zu 'konstruieren' und zu 'starten'.
Nach dem Start läuft der 'Thread' parallel und die Methode processDBLoad(. . .) wartet nicht auf das Ende von DB_Load__Thread.

/*
 * Methode die ausgeführt wird wenn die SQL-Kommandos aus der zuvor ausgewählten Datei
 * ausgeführt werden sollen. */
    private static void processDBLoad(DB_Load parmCallingFrame) {
. . . . .
. . . . .
/* 
 * Aufrufen der Methode, in der die Parameter für die Verbindung zur Datenbank ermittelt werden. */
      conToDatabase = processConnectToDatabase(parmCallingFrame, array_DB_Parms);
/* 
 * Wenn eine 'Connection zur Datenbank hergestellt werden konnte dann den Thread
 * für das Einlesen der Datei mit den SQL-Kommandos und deren Ausführung starten. */
      
if (conToDatabase != null) {
        DB_Load__Thread t =
new DB_Load__Thread(parmCallingFrame);
        t.start();
      }

    }

zum Inhaltsverzeichnis

Zwischen-Test

Bevor der umfangreiche endgültige Code für das Einlesen und Ausführen der SQL-Kommandos geschrieben wird, wird getestet, ob die Klasse DB_Load__Thread wie erwartet gestartet wird.

Dazu wird – wie schon bekannt – Run > Run ausgewählt.

Anschließend wird mit der Schaltfläche [ Auswahl der SQL-Kommando-Datei ] die Datei mit den Parametern ausgewählt.

Nach dem Anklicken der Schaltfläche [ Start SQL-Kommandos ] werden zuerst die Parameter für die Verbindung zur Datenbank und anschließend das Ergebnis des vorläufigen Codes - die Zahlen 1 bis 20 - angezeigt.



zum Inhaltsverzeichnis

Zusätzlicher Code

Bei der Klasse DB_Load__Thread muß der temporäre Code durch den endgültigen Code für das Öffnen und Lesen der sequentiellen Datei mit den SQL-Kommandos ersetzt werden.

Zum leichteren Erkennen der geänderten oder zusätzlichen Code-Teile sind diese fett geschrieben.
Es wird empfohlen, den bestehenden Code Schritt für Schritt durch die nachfolgend erklärten Code-Teile zu ersetzen.

zum Inhaltsverzeichnis

Import in der Klasse DB_Load__Thread

package js_intro02.client;
 
import java.io.*;
import
java.sql.*;
/**
 *
 * @author kurt@javascout.biz

Für das Öffnen und Lesen der sequentiellen Datei und für die Ausführung der SQL-Kommandos gegen die Datenbank.

zum Inhaltsverzeichnis

Globale Variablen und 'Constructor' der Klasse DB_Load__Thread

 *
 */

public class DB_Load__Thread extends Thread {
/*
 * Variable, die auf die Klasse mit der GUI verweist.
 * Damit kann periodisch die jeweilige Zahl auf der GUI angezeigt werden. */
    DB_Load frmCallingFrame;
/*
 * Variable, die auf die 'Connection' zum Datanbanksystem verweist. */
    Connection ConToDatabase;
/* 
 * 'Constructor' der Klasse.
 * Der als Parameter übergebene Wert wird als 'final' definiert.
 * Das bedeutet, daß sich der Wert des Parameters nicht ändert während der 'Thread'
 * ausgeführt wird und mit 'final' wird die Performance verbessert. */
      public DB_Load__Thread(final DB_Load parmCallingFrame,
                             
final Connection parmConToDatabase) {
/*
 * Die als Parameter übergebenen Werte werden in den Variablen dieser Klasse gespeichert. */
      frmCallingFrame = parmCallingFrame;
      ConToDatabase = parmConToDatabase;
    }

Für die Verbindung zur Datenbank muß auch der 'Connector' beim 'Konstruieren' der Klasse als Parameter übergeben werden und als Variable der Klasse 'aufgehoben' werden.

zum Inhaltsverzeichnis

Start des Thread in der Methode processDBLoad(. . .) / Klasse DB_Load__ActionHandler

/* 
 * Aufrufen der Methode, in der die Parameter für die Verbindung zur Datenbank ermittelt werden. */
      conToDatabase = processConnectToDatabase(parmCallingFrame, array_DB_Parms);
/* 
 * Wenn eine 'Connection zur Datenbank hergestellt werden konnte dann den Thread
 * für das Einlesen der Datei mit den SQL-Kommandos und deren Ausführung starten. */
      
if (conToDatabase != null) {
        DB_Load__Thread t =
new DB_Load__Thread(parmCallingFrame, conToDatabase);
        t.start();
      }
    }

Neu gegenüber dem temporären Code ist, daß auch der Wert für die 'Connection' zur Datenbank übergeben werden muß.
Das ist die einzige Änderung in der Klasse
DB_Load__ActionHandler in diesem Schritt.

zum Inhaltsverzeichnis

Code zum Einlesen der Datei mit den SQL-Kommandos / Klasse DB_Load__Thread

/* 
 * Die Methode 'run' wird automatisch gestarted nachdem das Objekt 'konstruiert' wurde. */
    public void run() {
/*
 * Eine Klasse mit der Superklasse 'Thread' braucht eine Fehlerbehandlung
 * für den Fall, daß die Ausführung von 'außen', d.h. durch die aufrufende Methode,
 * unterbrochen wurde. Deswegen die try/catch-Logik. */
      
try {
/*
 * Um die Ausgabe auf der GUI klarer erkennbar zu machen wird ein Trennstrich angezeigt. */
        
frmCallingFrame.get_txt_Report().append("------------------\n");
/*
 * Der Name der Datei mit den SQL-Kommandos wird aus dem Feld der GUI übernommen. */
        
String strInputFileName = frmCallingFrame.get_txt_InputFile().getText();
/*
 * Öffnen der Datei; dazu werden Methoden vom package 'java.io' verwendet. */

        LineNumberReader InputStream = new LineNumberReader(new FileReader(strInputFileName));
/*
 * Erste Zeile der Datei wird gelesen. */

        String strLineRead = InputStream.readLine();
/*
 * Wenn die Datei leer ist wird gleich eine Fehlermeldung ausgegeben. */
        
if (strLineRead == null) {
          frmCallingFrame.get_txt_Report().append("Eingabe-Datei ist leer !\n");
        }
/*
 * In einer Schleife jede Zeile der Datei lesen und eine eigene Methode aufrufen
 * in der das SQL-Kommando gegen die Datenbank ausgeführt wird.
 * Die Schleife wird abgebrochen wenn eine weitere Zeile nicht mehr gelesen werden kann. */
        
while (strLineRead != null) {
/* Gelesene Zeile zur Kontrolle auf der GUI ausgegeben. */
          
frmCallingFrame.get_txt_Report().append(
              
"Bearbeitete Zeile aus der Datei: " + strLineRead + "\n");
/*
 * Ausführen des SQL-Kommandos gegen die Datenbank erfolgt in einer eigenen
 * Methode.
 * Grund dafür ist, daß ein eigener try/catch Rahmen notwendig ist um bei
 * einem fehlerhaften SQL-Kommando nicht in die 'catch'-Logik dieses try/catch Rahmens
 * zu kommen.
 * Dann würde nämlich die Verarbeitung abgebrochen und die weiteren SQL-Kommandos
 * nicht ausgeführt. */

          processDBOperation(strLineRead);
/*
 * Nächste Zeile der Datei wird gelesen. */

          strLineRead = InputStream.readLine();
        }
      }
      
catch (Exception e) {
/*
 * Unerwartetes Ende des Threads; Fehlermeldung auf der GUI ausgeben. */
        
frmCallingFrame.get_txt_Report().append(
            
"Unerwartetes Ende von DB_Load__Thread: " + e.toString() + "\n");
      }
    }


Für das Öffnen und Lesen einer sequentiellen Datei gibt es in Java zahlreiche Möglichkeiten.
Der verwendete Code greift auf Java-Funktionen für das Lesen von ganzen Zeilen aus einer sequentiellen Datei mit Text zurück.

In einer while-Schleife wird dann Zeile für Zeile aus der Datei gelesen und innerhalb der Schleife wird dann die Methode processDBOperation(. . .) aufgerufen.

zum Inhaltsverzeichnis

Code für die Methode processDBOperation(. . .) zum Ausführen der SQL-Kommandos / Klasse DB_Load__Thread

/*
 * Methode, die eine Zeile aus der Input-Datei als Parameter übernimmt,
 * prüft ob es nicht ein 'Kommentar' (Zeile beginnt mit '//') ist,
 * das SQL-Kommando an das Datenbanksystem übergibt
 * und anschließend eine Bestätigung oder eine Fehlermeldung auf der GUI ausgibt. */
    private void processDBOperation(String parmstrSQLCommand) {
/*
 * try/catch Logik damit Fehler bei der Datenbank-Operation abgefangen werden können. */
      try {
/*
 * Prüfen ob die im Paramater übergebene Zeile ein Kommentar ist.
 * Eine Kommentar-Zeile beginnt mit '//'. */
        int intCommentPosition = parmstrSQLCommand.indexOf("//");
/*
 * Wenn die Zeile ein Kommentar ist wird die Verarbeitung in dieser Methode beendet. */
        if ((intCommentPosition >= 0) && (intCommentPosition <= 1)) return;
/*
 * Die im Parameter übergebene Zeile ist kein Kommentar;
 * SQL-Operation auf der Datenbank ausführen. */
/*
 * Zuerst ein 'Statement', das das SQL-Kommando an die Datenbank weitergeben kann,
 * 'konstruieren'. */
        Statement SQLStatement = ConToDatabase.createStatement();
/*
 * Das 'Statement' ausführen; d.h. das SQL-Kommando an die Datenbank übergeben. */
        SQLStatement.executeUpdate(parmstrSQLCommand);
/*
 * Wenn der Code bis hierher gekommen ist, dann wurde das SQL-Kommando
 * ohne Fehler ausgeführt. Rückmeldung auf der GUI ausgeben. */
        
frmCallingFrame.get_txt_Report().append("SQL-Kommando ausgeführt.\n");
      }
      catch
(SQLException SQLExc) {
/*
 * Beim Ausführen des SQL-Kommandos ist ein Fehler aufgetreten;
 * Fehlermeldung auf der GUI ausgeben. */
        frmCallingFrame.get_txt_Report().append(
            
"Fehler beim Ausführen des SQL-Kommandos: " + SQLExc.toString() + "\n");
      }
    }

Wie schon im Kommentar der Methode beschrieben, wurde das Ausführen der SQL-Kommandos in einer eigenen Methode aus folgendem Grund gewählt:
Das Erkennen von Fehlern bei der Ausführung von SQL-Kommandos erfolgt in einem
try/catch-Rahmen.
Ein Fehler in einem SQL-Kommando ist aber kein Grund, die weitere Verarbeitung des Programms abzubrechen – das würde aber passieren wenn das Ausführen der SQL-Kommandos innerhalb des
try/catch-Rahmens in der Methode run() erfolgen würde.

Die Verarbeitung einer Zeile aus der eingelesenen Datei erfolgt in folgenden Schritten:

zum Inhaltsverzeichnis

Datei mit den SQL-Kommandos erstellen.

Per Definition muß die Datei mit den SQL-Kommandos im selben Verzeichnis erstellt werden wie die Datei mit der XML-Struktur mit den Parametern für die Verbindung zum Datenbanksystem (siehe Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02 – XML-Struktur lesen > Verzeichnis und Datei mit der XML-Struktur erstellen).

Für das Anlegen der Datei wird das gerade angelegte Verzeichnis ('DB_Input' in diesem Beispiel) mit der rechten Maustaste angeklickt und aus dem Kontext Menu New > File ausgewählt.


Im darauf hin erscheinenden Fenster (New File) wird der 'File name' erfaßt (SQL_Kommandos.txt im Beispiel) und durch Anklicken der Schaltfläche [  Finish  ] bestätigt.
Damit wird auch das Fenster wieder geschlossen.


Die gerade erstellte Datei wird mit folgenden SQL-Kommandos gefüllt.

drop table LANGUAGE;
create table LANGUAGE (IsoCode char(2) primary key not null);
alter table LANGUAGE add column LongName varchar(62);
alter table LANGUAGE add column SpokenBy bigint;
insert into LANGUAGE values ('de', 'Deutsch', 100000000);
insert into LANGUAGE values ('en', 'Englisch', 1000000000);
insert into LANGUAGE values ('zh', 'Chinesisch', 1300000000);

Die SQL-Kommandos erstellen eine Datenbank-Tabelle, in der für verschiedene Sprachen der ISO-Code, der Name der Sprache und die Zahl der Menschen, die diese Sprache spricht, gespeichert werden kann.

zum Inhaltsverzeichnis



Gesamter Code am Ende dieses Schrittes

Klasse DB_Load

Der Code dieser Klasse wurde in diesem Schritt nicht verändert.
Für eine Liste des gesamten Codes folgen Sie bitte dem Link zu
Tutorial: Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) - ActionHandler > Gesamter Code am Ende diesen Schrittes.

zum Inhaltsverzeichnis

Klasse DB_Load__ActionHandler

package js_intro02.client;
 
import
java.awt.*;
import
java.awt.event.*;
import
java.io.*;
import
java.sql.*;
import
org.jdom.*;
import
org.jdom.input.*;
/**
 *
 * @author kurt@javascout.biz
 * @date 2008-02-07
 *
 * @description
 *  Klasse mit statischen Methoden die ausgeführt werden wenn ein 'event'
 *  (z.B. der Klick einer Maustaste) aufgetreten ist.
 *  Detail-Dokumentation finden Sie bei den einzelnen Methoden.
 *
 * @change-log
 * when         who               why
 * --------------------------------------------------------
 *
 */

public class DB_Load__ActionHandler {
/*
 * Methode die ermittelt, bei welchem GUI-Element ein 'ActionEvent' ausgelöst wurde
 * und die entsprechende Methode aufruft. */
    public static void handleEvent(DB_Load parmCallingFrame, ActionEvent parmActionEvent) {
/* Zuerst wird die 'Identifikation' des GUI-Element aus dem ActionEvent extrahiert. */
      String cmd = parmActionEvent.getActionCommand().trim();
/* Je nach Auslöser des Events wird die entsprechende Methode aufgerufen. */
      if(cmd.equals("btn_Select")) processSelectFile(parmCallingFrame);
      if(cmd.equals("btn_Start")) processDBLoad(parmCallingFrame);
    }

/*
 * Methode die ausgeführt wird wenn die Datei mit den SQL-Kommandos ausgewählt werden soll. */
    public static void processSelectFile(DB_Load parmCallingFrame) {
/* 
 * Fenster für den 'File-dialog' aufrufen;
 * in diesem kann der Benutzer eine Datei auswählen. */
      FileDialog fd = new FileDialog(parmCallingFrame,
                                     
"Bitte wählen Sie die Datei mit den SQL-Kommandos",
                                     FileDialog.
LOAD);
/* 
 * Anfangswerte für Verzeichnis und Dateiname setzen und Fenster sichtbar machen. */
      fd.setFile("");
      fd.setDirectory("");
      fd.setVisible(true);
/* 
 * Name für gewähltes Verzeichnis und Datei aus dem 'File-dialog' holen
 * und einen String bilden. */
      String strDirectoryAndFileName = fd.getDirectory() + fd.getFile();
/* 
 * Verzeichnis und Datei-Name im entsprechenden Feld anzeigen. */
      parmCallingFrame.get_txt_InputFile().setText(strDirectoryAndFileName);
    }
/*
 * Methode die ausgeführt wird wenn die SQL-Kommandos aus der zuvor ausgewählten Datei
 * ausgeführt werden sollen. */
    private static void processDBLoad(DB_Load parmCallingFrame) {
/* 
 * Damit diese Methode nicht überladen wird, werden eigene Methoden
 * für das Ermitteln der Paramater für die Verbindung zur Datenbank,
 * für das Aufbauen der Verbindung zur Datenbank und
 * für das Ausführen der SQL-Kommandos
 * aufgerufen. */
/* 
 * Die Übergabe der Parameter für die Verbindung zur Datenbank erfolgt durch
 * ein String-Array. */
      String[] array_DB_Parms;
/* 
 * Aufrufen der Methode, in der die Parameter für die Verbindung zur Datenbank ermittelt werden. */
      array_DB_Parms = processGetDBParms(parmCallingFrame);
/* 
 * Prüfen, ob alle DB-Parameter ermittelt werden konnten;
 * bei fehlenden Werten wird ein Array ohne Elemente zurückgeliefert.
 * In diesem Fall wird die Methode beendet; es erfolgt keine weitere Verarbeitung. */
      if (array_DB_Parms.length <= 0) return;
/* 
 * Die Verbindung (connection) zum Datenbanksystem wird in einer eigenen Methode eröffnet.
 * Die folgende Variable wird zum Prüfen, ob der Aufbau der Verbindung erfolgreich war, und
 * zur Weitergabe an die Methode, in der die SQL-Kommandos ausgeführt werden, verwendet. */
      Connection conToDatabase = null;
/* 
 * Aufrufen der Methode, in der die Parameter für die Verbindung zur Datenbank ermittelt werden. */
      conToDatabase = processConnectToDatabase(parmCallingFrame, array_DB_Parms);
/* 
 * Wenn eine 'Connection zur Datenbank hergestellt werden konnte dann den Thread
 * für das Einlesen der Datei mit den SQL-Kommandos und deren Ausführung starten. */
      
if (conToDatabase != null) {
        DB_Load__Thread t =
new DB_Load__Thread(parmCallingFrame, conToDatabase);
        t.start();
      }
    }
/*
 * Methode die aus der Datei mit der XML-Struktur die Parameter für die Verbindung
 * zur Datenbank ausliest.
 * Die Parameter werden im String-Array an die aufrufende Methode zurückgerufen */
    private static String[] processGetDBParms(DB_Load parmCallingFrame) {
/* 
 * Die Übergabe der Parameter für die Verbindung zur Datenbank erfolgt durch
 * ein String-Array. */
      String[] array_DB_Parms = new String[4];
/* 
 * Extrahieren des Verzeichnis-Namens aus dem im Text-Feld enthaltenen
 * String mit Verzeichnis und Datei-Namen für die Datei mit den SQL-Kommandos. */
      String strDirectoryName = parmCallingFrame.get_txt_InputFile().getText();
/* 
 * Trennen von Verzeichnis und Datei durch den System-spezifischen 'file-separator'. */
      String strDirectorySeparator = System.getProperty("file.separator");
/* 
 * Postion des letzten 'file-separator' in der Zeichenkette ermitteln. */
      int intLastDirectorySeparator = strDirectoryName.lastIndexOf(strDirectorySeparator);
/* 
 * Wenn kein 'file-separator' vorhanden ist dann kann die Zeichenkette nicht
 * 'sinnvoll' sein: In diesem Fall Fehlermeldung im Report-Bereich der GUI ausgeben. */
      if (intLastDirectorySeparator <= 0) {
        parmCallingFrame.get_txt_Report().append(
            
"Ungültiger Verzeichnis-/Datei-Name: " + strDirectoryName + "\n");
/* Zum Zeichen eines Fehlers ein leeres Array zurückliefern. */
        return new String[0];
      }

/* 
 * Extrahieren des Teiles mit dem Verzeichnis. */
      strDirectoryName = strDirectoryName.substring(0, intLastDirectorySeparator + 1);
/* 
 * 'Bauen' der Zeichenkette mit Verzeichnis- und Datei-Name für die Datei
 * mit der XML-Struktur, die die Parameter enthält. */
      strDirectoryName += "DB_Connection.xml";
/* 
 * Kompletten String zur Kontrolle im Report-Bereich der GUI ausgeben. */

      parmCallingFrame.get_txt_Report().append(
            
"Datei mit den Datenbank-Parametern: " + strDirectoryName + "\n");
/* 
 * XML-Element, daß den 'Einstieg' in die hierarchische XML-Struktur ermöglicht. */
      
Element XML_RootElement;
/* 
 * Öffnen der Datei mit der XML-Struktur.
 * Die Klassen und Methoden sind im package org.jdom.input enthalten. */

      
try {
/* Damit das Öffnen auch mit Windows-Betriebssystemen funktioniert,
 * muß an den SAXBuilder eine 'file' übergeben werden. */ 
        File f = new File(strDirectoryName);
/* Die Klasse SAXBuilder ermöglicht ein einfaches Bearbeiten einer Datei
 * mit einer XML-Struktur, die dem Document-Object_Model (DOM) entspricht. */ 
        SAXBuilder parser = new SAXBuilder();
/* Das 'document' enthält dann die gesamte XML-Struktur aus der Datei. */ 
        Document document = parser.build(f);
/* Das Einstiegselement der XML-Struktur wird 'ergriffen'. */ 
        XML_RootElement = document.getRootElement();
      }
      
catch(JDOMException e) {
/* 
 * Fehler: Datei enthält keine XML-Struktur entsprechend dem DOM.
 * Meldung im Report-Bereich der GUI ausgeben. */
        parmCallingFrame.get_txt_Report().append(
            
"'Not well formed exception' beim Öffnen der Datei: " +
            strDirectoryName +
"\n");
/* Zum Zeichen eines Fehlers ein leeres Array zurückliefern. */
        return new String[0];
      }
      
catch(Exception e) {
/* 
 * Anderer Fehler beim Versuch, die Datei mit der XML-Struktur zu öffnen.
 * Meldung im Report-Bereich der GUI ausgeben. */
        parmCallingFrame.get_txt_Report().append(
            
"Anderer Fehler (als XML-Problem) beim Öffnen der Datei: " +
            strDirectoryName +
"\n");
/* Zum Zeichen eines Fehlers ein leeres Array zurückliefern. */
        return new String[0];
      }
/* 
 * Die verwendete XML-Struktur ist sehr einfach weil alle XML-Elemente mit den Parametern
 * direkt 'unter' dem 'root'-Element angeordnet sind. */
/* 
 * Methoden des packagage 'org.jdom.*' extrahieren die Werte der einzelnen XML-Einträge
 * wenn der Name des XML-Eintrags angegeben wird. */
/* 
 * Zur Vereinfachung wird nur eine Variable für alle XML-Einträge verwendet. */

      Element elementSingleParm;

/* 
 * Extrahieren des Namens der Datei mit der Klasse, die die Verbindung zum Datenbanksystem
 * herstellt. */

      elementSingleParm = XML_RootElement.getChild(
"DataBaseDriverName");
      
if (elementSingleParm == null) {
/* XML-Eintrag mit Namen 'DataBaseDriverName' nicht gefunden.
 * Fehler im Report-Bereich der GUI ausgeben und zum Zeichen eines Fehlers
 * ein leeres String-Array an die aufrufende Methode zurückliefern. */

        parmCallingFrame.get_txt_Report().append(
            
"XML-Eintrag 'DataBaseDriverName' nicht vorhanden.\n");
        
return new String[0];
      }

/* 
 * Wert des XML-Eintrages in den vorgesehenen String des String-Arrays übernehmen. */
      array_DB_Parms[0] = elementSingleParm.getTextTrim();;
/* Zur Kontrolle des Programm-Fortschrittes den Wert im Report-Bereich der GUI anzeigen. */
        parmCallingFrame.get_txt_Report().append(
            
"DataBaseDriverName: " + array_DB_Parms[0] + "\n");
/* 
 * Extrahieren des Namens der Datenbank inklusive der spezifizierenden Zeichen. */

      elementSingleParm = XML_RootElement.getChild(
"DataBaseName");
      
if (elementSingleParm == null) {
/* XML-Eintrag mit Namen 'DataBaseName' nicht gefunden.
 * Fehler im Report-Bereich der GUI ausgeben und zum Zeichen eines Fehlers
 * ein leeres String-Array an die aufrufende Methode zurückliefern. */

        parmCallingFrame.get_txt_Report().append(
            
"XML-Eintrag 'DataBaseName' nicht vorhanden.\n");
        
return new String[0];
      }

/* 
 * Wert des XML-Eintrages in den vorgesehenen String des String-Arrays übernehmen. */
      array_DB_Parms[1] = elementSingleParm.getTextTrim();;
/* Zur Kontrolle des Programm-Fortschrittes den Wert im Report-Bereich der GUI anzeigen. */
        parmCallingFrame.get_txt_Report().append(
            
"DataBaseName: " + array_DB_Parms[1] + "\n");
/* 
 * Extrahieren des Benutzer-Namens für den Datenbank-Zugriff. */

      elementSingleParm = XML_RootElement.getChild(
"DataBaseUserID");
      
if (elementSingleParm == null) {
/* XML-Eintrag mit Namen 'DataBaseUserID' nicht gefunden.
 * Fehler im Report-Bereich der GUI ausgeben und zum Zeichen eines Fehlers
 * ein leeres String-Array an die aufrufende Methode zurückliefern. */

        parmCallingFrame.get_txt_Report().append(
            
"XML-Eintrag 'DataBaseUserID' nicht vorhanden.\n");
        
return new String[0];
      }

/* 
 * Wert des XML-Eintrages in den vorgesehenen String des String-Arrays übernehmen. */
      array_DB_Parms[2] = elementSingleParm.getTextTrim();;
/* Zur Kontrolle des Programm-Fortschrittes den Wert im Report-Bereich der GUI anzeigen. */
        parmCallingFrame.get_txt_Report().append(
            
"DataBaseUserID: " + array_DB_Parms[2] + "\n");
/* 
 * Extrahieren des Passworts für den Datenbank-Zugriff. */

      elementSingleParm = XML_RootElement.getChild(
"DataBasePassword");
      
if (elementSingleParm == null) {
/* XML-Eintrag mit Namen 'Password' nicht gefunden.
 * Fehler im Report-Bereich der GUI ausgeben und zum Zeichen eines Fehlers
 * ein leeres String-Array an die aufrufende Methode zurückliefern. */

        parmCallingFrame.get_txt_Report().append(
            
"XML-Eintrag 'DataBasePassword' nicht vorhanden.\n");
        
return new String[0];
      }

/* 
 * Wert des XML-Eintrages in den vorgesehenen String des String-Arrays übernehmen. */
      array_DB_Parms[3] = elementSingleParm.getTextTrim();;
/* Zur Kontrolle des Programm-Fortschrittes den Wert im Report-Bereich der GUI anzeigen. */
        parmCallingFrame.get_txt_Report().append(
            
"DataBasePassword: " + array_DB_Parms[3] + "\n");
/* 
 * Zurückliefern des String-Arrays mit den Parametern. */
      return array_DB_Parms;
    }

/*
 * Methode, die die Verbindung (connection) zur Datenbank herstellt.
 * Die 'connection' wird von der Methode zurückgeliefert. */
    private static Connection processConnectToDatabase(
                                  DB_Load parmCallingFrame, String[] parmArray_DB_Parms) {
/*
 * Variable, die von der Methode zurückgeliefert wird. */

      Connection conToDatabase =
null;
/* */
      try {
/*
 * Klasse für die Verbindung zum Datenbanksystem 'konstruieren'.
 * Diese Klasse wird vom Hersteller des Datenbanksystems mitgeliefert und kann
 * deswegen nicht statisch im Code definiert werden.
 * Für dieses Beispiel wurde der Name der Klasse über die Parameter in der XML-Struktur
 * eingelesen.
 * Die Bibliotheks-Datei (*.jar) muß beim Start des Programms in der Liste der *.jar-Datein
 * enthalten sein.
 * Das Konstruieren der Klasse erfolgt mit der Java-Klasse 'Class'. */
        Class.forName(parmArray_DB_Parms[0]);
/*
 * Als Konvention (für Java festgelegt) heißt die 'konstruierte' Klasse für die Verbindung
 * zum Datenbanksystem 'DriverManager'.
 * Das erfolgreiche 'Konstruieren' wird auf der GUI gemeldet. */
        parmCallingFrame.get_txt_Report().append(
            
"'DriverManager' konstruiert für: " + parmArray_DB_Parms[0] + "\n");
/*
 * Der 'DriverManager' enhält eine Methode mit der die Verbindung zu einer Datenbank
 * des Datenbanksystems erstellt werden kann.
 * Dazu muß der Name der Datenbank, ein berechtigter Benutzer und dessen Passwort
 * an die Methode als Parameter übergeben werden. */
        conToDatabase = DriverManager.getConnection(
            parmArray_DB_Parms[1], parmArray_DB_Parms[2], parmArray_DB_Parms[3]);

/*
 * Das erfolgreiche Verbinden zu Datenbank wird auf der GUI gemeldet. */
        parmCallingFrame.get_txt_Report().append(
            
"Verbindung erfolgreich zur Datenbank: " + parmArray_DB_Parms[1] + "\n");
/*
 * Zur Vereinfachung der Verarbeitung 'darf' das Datenbanksystem entscheiden wann
 * ein 'Commit' ausgeführt wird.
 * Diese Einstellung wird für das Tutorial gewählt um eventuelle Fehler durch ein
 * vergessenes 'Commit' zu vermeiden.
 * Für reale Entwicklungen soll diese Einstellung nicht verwendet werden
 * weil im 'Echtbetrieb' ein 'Commit' oder 'Rollback' so gesetzt werden muß,
 * daß die Integrität der Daten gewahrt bleibt - auch wenn ein Fehler auftritt. */
        conToDatabase.setAutoCommit(true);
      }

      catch
(Exception Exc) {
/*
 * Verbinden zur Datenbank war nicht erfolgreich;
 * Fehler auf der GUI melden und den zurückgelieferten Wert auf 'null' setzen
 * als Zeichen, daß das Programm abgebrochen werden muß. */
        parmCallingFrame.get_txt_Report().append(
            
"Fehler beim Verbinden zur Datenbank: " + Exc.toString() + "\n");
        conToDatabase =
null;
      }
/*
 * Erstellte Verbindung zur Datenbank an die aufrufende Methode zurückliefern. */
      return conToDatabase;
    }
}

zum Inhaltsverzeichnis

Klasse DB_Load__Thread

package js_intro02.client;
 
import
java.io.*;
import
java.sql.*;
/**
 *
 * @author kurt@javascout.biz
 * @date 2008-02-14
 *
 * @description
 *  Klasse mit einem 'Thread', der die Datei mit den SQL-Kommandos öffnet,
 *  diese Datei Zeile für Zeile liest (jede Zeile enthält ein SQL-Kommando),
 *  diese SQL-Kommandos an die Datenbank übergibt und
 *  das SQL-Kommando und eventuelle Fehlermeldungen auf der GUI ausgibt.
 *
 * @change-log
 * when         who               why
 * --------------------------------------------------------
 *
 */

public class DB_Load__Thread extends Thread {
/*
 * Variable, die auf die Klasse mit der GUI verweist.
 * Damit kann periodisch die jeweilige Zahl auf der GUI angezeigt werden. */
    DB_Load frmCallingFrame;
/*
 * Variable, die auf die 'Connection' zum Datanbanksystem verweist. */
    Connection ConToDatabase;
/* 
 * 'Constructor' der Klasse.
 * Der als Parameter übergebene Wert wird als 'final' definiert.
 * Das bedeutet, daß sich der Wert des Parameters nicht ändert während der 'Thread'
 * ausgeführt wird und mit 'final' wird die Performance verbessert. */
    public DB_Load__Thread(final DB_Load parmCallingFrame,
                             
final Connection parmConToDatabase) {
/*
 * Die als Parameter übergebenen Werte werden in den Variablen dieser Klasse gespeichert. */
      frmCallingFrame = parmCallingFrame;
      ConToDatabase = parmConToDatabase;
    }
/* 
 * Die Methode 'run' wird automatisch gestarted nachdem das Objekt 'konstruiert' wurde. */
    public void run() {
/*
 * Eine Klasse mit der Superklasse 'Thread' braucht eine Fehlerbehandlung
 * für den Fall, daß die Ausführung von 'außen', d.h. durch die aufrufende Methode,
 * unterbrochen wurde. Deswegen die try/catch-Logik. */
      
try {
/*
 * Um die Ausgabe auf der GUI klarer erkennbar zu machen wird ein Trennstrich angezeigt. */
        
frmCallingFrame.get_txt_Report().append("------------------\n");
/*
 * Der Name der Datei mit den SQL-Kommandos wird aus dem Feld der GUI übernommen. */
        
String strInputFileName = frmCallingFrame.get_txt_InputFile().getText();
/*
 * Öffnen der Datei; dazu werden Methoden vom package 'java.io' verwendet. */

        LineNumberReader InputStream = new LineNumberReader(new FileReader(strInputFileName));
/*
 * Erste Zeile der Datei wird gelesen. */

        String strLineRead = InputStream.readLine();
/*
 * Wenn die Datei leer ist wird gleich eine Fehlermeldung ausgegeben. */
        
if (strLineRead == null) {
          frmCallingFrame.get_txt_Report().append("Eingabe-Datei ist leer !\n");
        }
/*
 * In einer Schleife jede Zeile der Datei lesen und eine eigene Methode aufrufen
 * in der das SQL-Kommando gegen die Datenbank ausgeführt wird.
 * Die Schleife wird abgebrochen wenn eine weitere Zeile nicht mehr gelesen werden kann. */
        
while (strLineRead != null) {
/* Gelesene Zeile zur Kontrolle auf der GUI ausgegeben. */
          
frmCallingFrame.get_txt_Report().append(
              
"Bearbeitete Zeile aus der Datei: " + strLineRead + "\n");
/*
 * Ausführen des SQL-Kommandos gegen die Datenbank erfolgt in einer eigenen
 * Methode.
 * Grund dafür ist, daß ein eigener try/catch Rahmen notwendig ist um bei
 * einem fehlerhaften SQL-Kommando nicht in die 'catch'-Logik dieses try/catch Rahmens
 * zu kommen.
 * Dann würde nämlich die Verarbeitung abgebrochen und die weiteren SQL-Kommandos
 * nicht ausgeführt. */

          processDBOperation(strLineRead);
/*
 * Nächste Zeile der Datei wird gelesen. */

          strLineRead = InputStream.readLine();
        }
      }
      
catch (Exception e) {
/*
 * Unerwartetes Ende des Threads; Fehlermeldung auf der GUI ausgeben. */
        
frmCallingFrame.get_txt_Report().append(
            
"Unerwartetes Ende von DB_Load__Thread: " + e.toString() + "\n");
      }
    }
/*
 * Methode, die eine Zeile aus der Input-Datei als Parameter übernimmt,
 * prüft ob es nicht ein 'Kommentar' (Zeile beginnt mit '//') ist,
 * das SQL-Kommando an das Datenbanksystem übergibt
 * und anschließend eine Bestätigung oder eine Fehlermeldung auf der GUI ausgibt. */
    private void processDBOperation(String parmstrSQLCommand) {
/*
 * try/catch Logik damit Fehler bei der Datenbank-Operation abgefangen werden können. */
      try {
/*
 * Prüfen ob die im Paramater übergebene Zeile ein Kommentar ist.
 * Eine Kommentar-Zeile beginnt mit '//'. */
        int intCommentPosition = parmstrSQLCommand.indexOf("//");
/*
 * Wenn die Zeile ein Kommentar ist wird die Verarbeitung in dieser Methode beendet. */
        if ((intCommentPosition >= 0) && (intCommentPosition <= 1)) return;
/*
 * Die im Parameter übergebene Zeile ist kein Kommentar;
 * SQL-Operation auf der Datenbank ausführen. */
/*
 * Zuerst ein 'Statement', das das SQL-Kommando an die Datenbank weitergeben kann,
 * 'konstruieren'. */
        Statement SQLStatement = ConToDatabase.createStatement();
/*
 * Das 'Statement' ausführen; d.h. das SQL-Kommando an die Datenbank übergeben. */
        SQLStatement.executeUpdate(parmstrSQLCommand);
/*
 * Wenn der Code bis hierher gekommen ist, dann wurde das SQL-Kommando
 * ohne Fehler ausgeführt. Rückmeldung auf der GUI ausgeben. */
        frmCallingFrame.get_txt_Report().append("SQL-Kommando ausgeführt.\n");
      }
      catch
(SQLException SQLExc) {
/*
 * Beim Ausführen des SQL-Kommandos ist ein Fehler aufgetreten;
 * Fehlermeldung auf der GUI ausgeben. */
        frmCallingFrame.get_txt_Report().append(
            
"Fehler beim Ausführen des SQL-Kommandos: " + SQLExc.toString() + "\n");
      }
    }
}

zum Inhaltsverzeichnis

Test

Der Code für das Programm kann jetzt durch Auswahl von Run>Run ausgeführt werden.

Nach dem Anklicken der Schaltfläche [ Auswahl der SQL-Kommando-Datei ] erscheint der Dialog für die Auswahl der Datei.

Wählen Sie die Datei 'SQL_Kommandos.txt' im Verzeichnis 'DB_Input' und Bestätigen Sie die Auswahl durch Anklicken der Schaltfläche [ OK ].


Nach dem Anklicken der Schaltfläche [ Start SQL-Kommandos ] werden die SQL-Kommandos von der gewählten Datei eingelesen, an das Datenbanksystem weitergegeben und zur Kontrolle auf der GUI angezeigt.


Zur Kontrolle muß der MySQL-Datenbank-Monitor über die Kommandozeile aufgerufen werden.
Wenn Sie die Datenbank so eingerichtet haben wie bisher im Tutorial beschrieben, geben Sie auf der Kommandozeile folgenden Befehl ein:
mysql –host='127.0.0.1' –user='mysql' -p js_tutorial

Sie werden anschließend um das Passwort gefragt; wenn Sie das Beispiel aus dem Tutorial verwendet haben ist das Passwort
drowssap.

Im anschließend erscheinenden MySQL-Datenbank-Monitor können Sie den Inhalt der Tabelle 'LANGUAGE' mit folgendem SQL-Kommando abfragen:
select * from LANGUAGE;

Als Ergebnis sollten Sie den kompletten Inhalt der Tabelle sehen.




zum Inhaltsverzeichnis

Weitere Schritte und verwandte Dokumentation

Dokument

Inhalt

Tutorial: Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) – Meldungen drucken  

Im nächsten Schritt des Tutorials wird eine einfache Möglichkeit des Druckens vorgestellt.
Die verwendeten Methoden sind bereits ab Java 1.1 implementiert.
Eine mächtigere Möglichkeit für den Druck bietet Java ab Version 1.4 – Beispiele folgen !

Tutorial: Datenbank-Ladeprogramm mit Graphischer Benutzeroberfläche (Java_Intro_02) – Packen in JAR-Datei  

Wenn Sie wiederholen wollen, wie die Anwendung in eine Java-ARchiv- (JAR-) Datei gepackt wird und wie das Java-Programm außerhalb von Eclipse ausgeführt wird, finden Sie die Anleitung in diesem Dokument.

zum Inhaltsverzeichnis