Datenbankzugriff mit JDBC

Werbung
Programmieren / Java
Datenbankzugriff mit JDBC
Frage Nr. 13
Datenbankzugriff
mit JDBC
Ausarbeitung einer Maturafrage aus dem Fach
P r o g r a m m i e r e n
/
Andreas Hechenblaickner
5CDH | HTBLA Kaindorf/Sulm
Dipl.-Ing. Manfred Wilfling
Erstelldatum: 19. Februar 2003
Letzte Überarbeitung: 21. Mai 2003
J a v a
PUC | Datenbankzugriff mit JDBC
Inhaltsverzeichnis
Inhaltsverzeichnis
Inhaltsverzeichnis
2
1
Datenbankzugriff mit JDBC
3
1.1
JDBC: der Zugriff auf Datenbanken mit Java
3
1.2
Datenbanktreiber für den Zugriff
3
2
Datenbanken und ihre Treiber
5
2.1
Interbase
5
2.2
Die freie Datenbank MySQL
5
2.3
Oracle Enterprise Edition
6
3
Datenbankverbindung herstellen
7
3.1
Den Treiber laden
7
3.2
Verbindung zur Datenbank
7
4
Datenbankabfragen
9
4.1
SQL-Anweisungen ausführen
9
4.2
Ergebnisse einer Abfrage in ResultSet
9
4.3
Datenbankänderungen
11
4.4
Die Klasse SQLException
11
4.5
Vorbereitete Anweisungen – Prepared Statements
12
4.6
Transaktionen
13
Folienvorschlag
14
Zusammenfassung
15
Quellen
15
HTBLA Kaindorf/Sulm
Seite 2 von 15
PUC | Datenbankzugriff mit JDBC
1
Datenbankzugriff mit JDBC
Datenbankzugriff mit JDBC
Datenbankverwaltungssysteme (DBMS, engl. Database Management Systems)
arbeiten auf einer Datenbasis (Tabellen) die miteinander in Beziehung stehen.
Die Programme, die die Datenbasis kontrollieren, bilden die zweite Hälfe der
DBMS.
1.1
JDBC: der Zugriff auf Datenbanken mit Java
JDBC ist die Abkürzung für Java Database Connectivity und bezeichnet einen
Satz von Klassen und Methoden, um relationale Datenbanksysteme von Java zu
nutzen. Mit der JDBC-API und den JDBC-Treibern wird eine wirksame Abstraktion von Datenbanken erreicht, sodass durch die einheitliche Programmierschnittstelle die Funktionen differierender Datenbanken in gleicher Weise genutzt werden können. Das Lernen von verschiedenen Zugriffsmethoden für unterschiedliche Datenbanken der Hersteller entfällt. Jede Datenbank hat ihr eigenes Protokoll aber die Implementierung ist nur dem Datenbanktreiber bekannt.
Folgende Schritte sind für den Zugriff auf eine relationale Datenbank mit JDBC
erforderlich:
1. Installieren der JDBC-Datenbanktreiber.
2. Eine Verbindung zur Datenbank über den entsprechenden JDBC-Treiber für
das verwendete DBMS aufbauen.
3. Eine SQL-Anweisung erzeugen.
4. Ausführen der SQL-Anweisung.
5. Das Ergebnis der Anweisung holen.
6. Schließen der Datenbankverbindung.
1.2
Datenbanktreiber für den Zugriff
Damit wir JDBC nutzen können, benötigen wir einen passenden Treiber für die
Datenbank. Es gibt vier Treiber-Kategorien:
1. JDBC-ODBC-Bridge-Treiber
Eine JDBC-ODBC-Brücke wandelt die Aufrufe von JDBC in ODBC-Aufrufe der
Client-Seite um. Die Methoden sind nativ und daher nicht plattformunabhängig.
2. Native-API Java Driver
Diese Treiber übersetzen die JDBC-Aufrufe direkt in Aufrufe der DatenbankAPI. Die Methoden sind ebenfalls nativ.
HTBLA Kaindorf/Sulm
Seite 3 von 15
PUC | Datenbankzugriff mit JDBC
Datenbankzugriff mit JDBC
3. Netz-Protokoll All-Java Driver
Hier wird ein in Java programmierter Treiber genutzt, der beim Datenbankzugriff auf den Client geladen wird. Der Treiber kommuniziert nicht direkt
mit der Datenbank, sondern mit einer Middleware.
4. Native Protocol All-Java Driver
Diese Treiber sind vollständig in Java programmiert und kommunizieren direkt mit dem Datenbankserver.
Ein Kriterium ist, ob sie vollständig in Java implementiert und daher portabel
sind (Typ 3 und 4) oder plattformabhängigen Programmcode beinhalten (Typ 1
und 2). Applets können mit diesen plattformabhängigen Treibern nichts anfangen.
HTBLA Kaindorf/Sulm
Seite 4 von 15
PUC | Datenbankzugriff mit JDBC
2
Datenbanken und ihre Treiber
Datenbanken und ihre Treiber
Wir wollen uns im Folgenden mit einigen Datenbanken und ihren Treibern beschäftigen, die für den Zugriff unter Java geeignet sind. Diese Auflistung dient
nur zur Übersicht und ist keinesfalls vollständig.
2.1
Interbase
Die Datenbank Interbase 6.0 (http://www.interbase.com) von Borland implementiert viele Anforderungen aus dem ANSI-SQL-92. Interbase bietet gespeicherte Prozeduren oder Trigger und ist eine ausgewachsene performante Lösung. Borland stellt den Quellcode sowie die ausführbaren Dateien für Windows, Novell Netware und verschiedene UNIX-Versionen wie Linux und Solaris
zur Verfügung. Interbase kann auf dem Rechner leicht installiert werden und
benötigt wenig Hauptspeicher.
Firebird (http://firebird.sourceforge.net) ist die Open-Source-Version von Interbase. Der Lizenz-Unterschied zu Interbase wird in den FAQs erklärt.
JDBC-Treiber für Interbase
Für Java gibt es einen Java-Datenbanktreiber mit dem Namen InterClient
(http://firebird.sourceforge.net)
der
eine
hundertprozentige
Java-Implementierung ist.
2.2
Die freie Datenbank MySQL
MySQL (http://www.mysql.com) ist ein häufig eingesetzter freier und schneller
Open-Source-Datenbankserver. Er wird oft im Internet in Zusammenhang mit
dynamischen Webseiten eingesetzt; das Zusammenspiel Linux, Apache,
MySQL, PHP (LAMP-System) ist hoch gelobt.
Eine herausragende Eigenschaft ist Geschwindigkeit und Bedienbarkeit, die
teilweise darauf beruht, dass MySQL auf Transaktionen verzichtet. Seit der Version 4 kann eine alternative Datenbank-Engine aber auch Transaktionen ausführen.
JDBC-Treiber für MySQL
MySQL kann einfach über den stehenden Typ-4 JDBC-Treiber Connector/J bedient werden (http://www.mysql.com). Nach dem Entpacken muss das Treiber.jar-Archiv noch im Klassenpfad aufgenommen werden.
HTBLA Kaindorf/Sulm
Seite 5 von 15
PUC | Datenbankzugriff mit JDBC
2.3
Datenbanken und ihre Treiber
Oracle Enterprise Edition
Einer der bekanntesten Datenbanken stammt von Oracle. Um die Verbreitung
weiter zu erhöhen, ist die Firma dazu übergegangen, eine vollwertige Version
zum Download oder als CD freizugeben. Wer das Download nicht scheut, der
kann unter http://otn.oracle.com/software/content.html die Version für Windows, Linux und weitere Unixe herunterladen. Weiters ist auch ein JDBCTreiber für den Datenbankzugriff aus Java-Programmen erhältlich.
HTBLA Kaindorf/Sulm
Seite 6 von 15
PUC | Datenbankzugriff mit JDBC
3
Datenbankverbindung herstellen
Datenbankverbindung herstellen
Die Verbindung zu einer Datenbank wird über die Klasse DriverManager und
die Schnittstelle Connection aufgebaut. Alle verwendeten Pakete liegen unter
java.sql.* und müssen zunächst importiert werden.
1 import java.sql.*;
Vor der Ausführung der JDBC-Befehle muss ein passender Datenbanktreiber
geladen werden.
3.1
Den Treiber laden
Der Datenbanktreiber ist eine ganz normale Java-Klasse, die sich bei einem
Treibermanager automatisch anmeldet. Unsere Aufgabe ist es nur, ein TreiberObjekt einmal zu erzeugen. Um eine Klasse zur Laufzeit zu laden und so ein
Laufzeit-Objekt zu erstellen, gibt es mehrere Möglichkeiten. Eine davon nutzt
die statische Methode forName() der Klasse Class. Die Syntax für das Laden
der JDBC-ODBC-Bridge lautet somit:
1 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Um möglichst unabhängig zu bleiben, sollte die Klasse auch nicht hart einkodiert werden. Besser ist es, den Klassennamen in eine Property zu schreiben.
Da wir die Klasse nur laden, aber die Referenz auf den Klassen-Deskriptor nicht
benötigen, belassen wir es bei einem Aufruf und beachten den Rückgabewert
nicht. Diese Operation löst eine ClassNotFoundException aus, falls die Klasse
nicht gefunden wurde, der Treiber also nicht geladen werden konnte.
Datenbank
3.2
Borland Interbase
Klassenname für den JDBC-Treiber
interbase.interclient.Driver
MySQL
org.gjt.mm.mysql.Driver
Oracle
oracle.jdbc.driver.OracleDriver
PostgreSQL
org.postgresql.Driver
IBM DB2
com.ibm.db2.jdbc.net.DB2Driver
ODBC-Datenquellen
sun.jdbc.odbc.JdbcOdbcDriver
Verbindung zur Datenbank
Nach dem Laden des Treibers können wir eine Verbindung zur Datenbank mit
Hilfe
des
Connection-Objekts
aufbauen,
welches
von
DriverManager.getConnection() zurückgegeben wird. Eine Verbindung wird mit speziellen Optionen parametrisiert, unter anderem mit dem Treiber, der die Datenquelle anspricht. Alle Datenquellen sind durch eine besondere URL qualifiziert,
die folgendes Format besitzt:
jdbc:Subprotokoll:Datenquellenname
HTBLA Kaindorf/Sulm
Seite 7 von 15
PUC | Datenbankzugriff mit JDBC
Datenbank
Datenbankverbindung herstellen
Borland Interbase
Subprotokoll
interbase
Beispiel
jdbc:interbase://host/database.gdb
MySQL
mysql
jdbc:mysql://host:3306/database
Oracle
oracle:thin
jdbc:oracle:thin:@:1243:database
PostgreSQL
postgresql
jdbc:postgresql://host:5432/database
IBM DB2
db2
jdbc:db2://database
ODBCDatenquellen
odbc
jdbc:odbc:database
Verbindung aufbauen
Die getConnection()-Methode liefert nun ein Connection-Objekt, das mit der
Quelle verbunden ist. Die nachfolgende Anweisung verbindet uns mit einer Datenbank, die den Namen scotttiger.gdb trägt. Diesen Namen haben wir im
Datenquellen-Administrator festgelegt und er hat nichts mit dem Dateinamen
zu tun.
1 Connection connection = DriverManager.getConnection(
2
"jdbc:interbase://localhost/scotttiger.gdb",
3
"sysdba", "masterkey");
Die Methode getConnection() erwartet bis zu drei Parameter: Die URL der Datenbank, zu der die Verbindung aufgenommen werden soll, ist der Pflichtparameter. Der Anmeldename und das Passwort sind optional. Meldet getConnection() keinen Fehler, so liefert sie uns eine geöffnete Datenbankverbindung.
Verbindung beenden
Um die Datenbankverbindung zu beenden genügt ein Aufruf von:
1 connection.close();
HTBLA Kaindorf/Sulm
Seite 8 von 15
PUC | Datenbankzugriff mit JDBC
4
Datenbankabfragen
Datenbankabfragen
Mit einer gelungenen Verbindung lassen sich nun SQL-Kommandos absetzen,
und die Datenbank kann gesteuert werden.
4.1
SQL-Anweisungen ausführen
Für SELECT-Abfragen ist ein Statement-Objekt anzulegen. JDBC bietet dazu die
Methode createStatement() an, die eine SQLException auslösen kann. Dies ist
eine Methode des Connection-Objekts.
1 Statement stmt = connction.createStatement();
Um Informationen auszulesen, benutzen wir die SELECT-Befehle aus SQL und
geben sie durch die executeQuery()-Methode der Statement-Schnittstelle an.
Der Aufruf liefert uns die Ergebnisse als Zeilen in Form eines ResultSetObjekts. Wir benutzen executeQuery() für Abfragen und executeUpdate() bei
Update-, Insert- oder Delete-Operationen. Wieder dürfen wir das Auffangen
von SQLException nicht vergessen.
1 String query = "SELECT * FROM Tabellenname";
2 ResultSet rs = stmt.executeQuery(query);
An dieser Stelle sei noch einmal darauf hingewiesen, dass JDBC nicht in die
Zeichenketten hineinsieht, die es an den Treiber weiterleitet. Sind die SQLAnfragen also falsch, lassen sich Fehler schwer finden. So kann zum Beispiel
schon die falsche Groß- beziehungsweise Kleinschreibung zu Fehlern in der Datenbank führen. Solche Fehler sind natürlich schwer zu entdecken. Daher bietet
es sich an, zum Testen erst die Kommandos auf der Konsole auszugeben. Insbesondere bei zusammengesetzten Ausdrücken finden sich dann die Fehler.
4.2
Ergebnisse einer Abfrage in ResultSet
Das Ergebnis einer Abfrage durch executeQuery() wird in einer Ergebnistabelle
vom Typ ResultSet zurückgegeben. Mit Methoden von ResultSet lassen sich
die unterschiedlichen Spalten ansprechen und die Zeilen auswerten.
Das Interface ResultSet bietet für jeden Datentyp eine entsprechende Methode getXXX() an – XXX ist der Datentyp. Da alle Spalten zusätzlich als String
ausgelesen werden können, ist es immer möglich, einfach getString() zu verwenden.
HTBLA Kaindorf/Sulm
Seite 9 von 15
PUC | Datenbankzugriff mit JDBC
Datenbankabfragen
getXXX-Methode
getInt()
Rückgabewert
int
SQL-Typ
getLong()
long
BIG INT
getFloat()
float
REAL
getDouble()
double
FLOAT
getBigDecimal()
BigDecimal
NUMBER
getBoolean()
boolean
BIT
getString()
String
VARCHAR, CHAR
getAsciiStream()
InputStream
LONGVARCHAR
getDate()
Date
DATE
getTime()
Time
TIME
getTimestamp()
Timestamp
TIME STAMP
getObject()
Object
jeder Typ
INTEGER
Auswertung
Um das ResultSet auszuwerten, müssen wir zunächst in die erste Zeile springen. Dies geschieht mit der next()-Methode von ResultSet. Danach sind wir mit
getXXX() in der Lage, die Spalten dieser Zeile auszuwerten. Um weitere Zeilen
zu erhalten, nutzen wir wieder next(). Die Methode gibt false zurück, falls es
keine neue Zeile mehr gibt. Die Abfragen befinden sich somit oft in einer whileSchleife.
1 while (rs.next()) {
2
System.out.print(rs.getString("bezeichnung") + "\t" +
3
rs.getInt("preis"));
4 }
Wird der Methode getXXX() ein String übergeben, so bestimmt dieser über den
Namen der Spalte. Alternativ kann auch ein numerischer Parameter übergeben
werden, der besagt die wievielte Spalte anzusprechen ist.
wasNull() bei ResultSet
Soll festgestellt werden, ob eine Spalte den Wert NULL hatte, so kann das nach
dem Aufruf der get-Methode durch Aufruf von wasNull() abgefragt werden.
wasNull() gibt genau dann true zurück, wenn die letzte abgefragte Spalte einen NULL-Wert als Inhalt hatte. Bei allen Spalten, die NULL-Werte enthalten
können, muss diese Abfrage also erfolgen. Bei den get-Methoden, die ein Objekt als Ergebniswert haben, geht es etwas einfacher. Hier wird null zurückgegeben, wenn der Spaltenwert NULL war.
HTBLA Kaindorf/Sulm
Seite 10 von 15
PUC | Datenbankzugriff mit JDBC
4.3
Datenbankabfragen
Datenbankänderungen
Datenbankänderungen werden mit den SQL-Anweisungen INSERT INTO, UPDATE oder DELETE FROM oder den SQL-DDL-Anweisungen (Data Definition
Language) zum Ändern der Datenbankstruktur durchgeführt. Im Gegensatz zu
Datenbankabfragen geben diese Anweisungen keine Ergebnismenge zurück,
sondern lediglich einen einzelnen Wert. Im Falle von INSERT INTO, UPDATE
und DELETE FROM gibt dieser Wert an, wie viele Datensätze von der Änderung
betroffen waren, bei DDL-Anweisungen ist er immer 0.
Um solche Anweisungen durchzuführen, stellt das Interface Statement die Methode executeUpdate() zur Verfügung, welche die Anzahl der betroffenen Zeilen als int zurückgibt.
4.4
Die Klasse SQLException
Wenn SQL-Anweisungen fehlschlagen, lösen sie normalerweise eine Ausnahme
des Typs SQLException aus. Das gilt sowohl, wenn keine Verbindung zur Datenbank zustande gekommen ist, als auch bei allen Arten von Syntaxfehlern in
SQL-Anweisungen. Auch bei semantischen Fehlern durch falsche Typisierung
oder inhaltlich fehlerhafte SQL-Anweisungen wird eine solche Ausnahme ausgelöst. SQLException ist eine Erweiterung der Klasse Exception und stellt folgende zusätzliche Methoden zur Verfügung:
int getErrorCode()
String getSQLState()
SQLException getNextException()
Mit getErrorCode() kann der herstellerspezifische Fehlercode abgefragt werden, getSQLState() liefert den internen SQL-Zustandscode. Etwas ungewöhnlich ist die Methode getNextException(), denn sie unterstützt die Verkettung
von Ausnahmen. Jeder Aufruf holt die nächste Ausnahme aus der Liste. Ist der
Rückgabewert null, gibt es keine weiteren Ausnahmen. Code zum Behandeln
einer SQLException könnte also etwa so aussehen:
1 ...
2 catch (SQLException e) {
3
do {
4
System.err.println(e.toString());
5
System.err.println("SQL-State: " + e.getSQLState());
6
System.err.println("ErrorCode: " + e.getErrorCode());
7
} while ((e = e.getNextException()) != null)
8 }
HTBLA Kaindorf/Sulm
Seite 11 von 15
PUC | Datenbankzugriff mit JDBC
4.5
Datenbankabfragen
Vorbereitete Anweisungen – Prepared Statements
Die SQL-Anweisungen, die mittels executeQuery() oder executeUpdate() an
die Datenbank gesendet werden, haben bis zur Ausführung im Datenbanksystem einige Umwandlungen vor sich. Zuerst müssen sie auf syntaktische Korrektheit getestet werden. Dann werden sie in einen internen Ausführungsplan
der Datenbank übersetzt und mit anderen Transaktionen optimal verzahnt.
Deutlich besser wäre es jedoch, eine Art Vorübersetzung für SQL-Anweisungen
zu nutzen.
Diese Vorübersetzung ist eine Eigenschaft, die JDBC unterstützt und die sich
Prepared Statements nennt. Vorbereitet (englisch prepared) deshalb, da die
Anweisungen in einem ersten Schritt zur Datenbank geschickt und dort in ein
internes Format umgesetzt werden. Später verweist ein Programm auf diese
vorübersetzten Anweisungen, und die Datenbank kann sie schnell ausführen,
da sie in einem optimalen Format vorliegen. Ein Geschwindigkeitsvorteil macht
sich immer dann besonders bemerkbar, wenn Schleifen Änderungen an Tabellenspalten vornehmen. Das kann durch die vorbereiteten Anweisungen schneller geschehen.
PreparedStatement-Objekt vorbereiten
Genauso wie ein Connection-Objekt eine Methode für ein Statement-Objekt
anbietet, werden PreparedStatement-Objekte angelegt. Dazu dient dann eine
Methode prepareStatement(). Als Parameter wird eine SQL-Zeichenkette übergeben, die den gleichen Aufbau wie etwa ein executeUpdate() hat. Einen
Unterschied werden wir jedoch feststellen: Bei den normalen StatementObjekten können wir dynamische Einträge einfach mit in den String einbauen.
Dies geht bei vorbereiteten Anweisungen nicht mehr. Woher sollte auch die
Anweisung wissen, was der Benutzer in seine Eingabemaske tippt? Damit jetzt
auch eine vorbereitete Anweisung Parameter enthalten kann, werden in die
Zeichenkette Platzhalter mit einem Fragezeichen eingefügt.
1 PreparedStatement updateLfrnt = connection.prepareStatement(
2
"UPDATE Lieferanten SET Adresse = ? WHERE Adresse LIKE ?");
Die Zeile instruiert die Datenbank, die Zeile zu interpretieren, in das interne
Format umzusetzen und vorbereitet zu halten. Im nächsten Schritt muss die
Anweisung für die Platzhalter Werte einsetzen.
Werte für die Platzhalter eines PreparedStatement
Bevor die executeUpdate()-Methode die vorbereitete Anweisung abarbeitet,
müssen die Platzhalter gefüllt werden. Dazu bietet das PreparedStatementObjekt für die Datentypen jeweils eine setXXX()-Methode an, die den Wert für
einen angegebenen Platzhalter setzt. So wird setInt(1,100) die Zahl 100 für
das erste Fragezeichen einsetzen. Nach der Zuweisung ist das Objekt für die
Ausführung bereit. executeUpdate() kann aufgerufen werden.
HTBLA Kaindorf/Sulm
Seite 12 von 15
PUC | Datenbankzugriff mit JDBC
Datenbankabfragen
1 updateLfrnt.setString(1, "Uferstraße 80");
2 updateLfrnt.setString(2, "Seestraße 78");
3 updateLfrnt.executeUpdate();
In einer Schleife lässt sich jetzt nun immer wieder executeUpdate() aufrufen,
und die schon gesetzten Parameter werden übernommen.
4.6
Transaktionen
Transaktionen sind für Datenbanken ein sehr wichtiges Konzept, denn nur dadurch bleibt die Integrität der Daten erhalten. Transaktionen sind vergleichbar
mit einer atomaren Ausführung bei Threads, mit dem Unterschied, dass die Datenbank inmitten einer gescheiterten Transaktion die bisher veränderten Werte
rückgängig macht.
In der Standard-Verarbeitung in JDBC wird jede SQL-Anweisung für sich als
Transaktion abgearbeitet. Dies nennt sich Auto-Commit. Um jedoch eine Folge
von Anweisungen in einer Transaktion auszuführen, muss zunächst das AutoCommit zurückgesetzt werden. Dann werden die Datenbankmanipulationen
ausgeführt, und die Transaktion kann anschließend abgeschlossen (commit)
oder zurückgesetzt (rollback) werden.
1 connection.setAutoCommit(false);
Werden alle Statements korrekt abgearbeitet, werden mit connection.commit() die Änderungen dauerhaft gemacht. Tritt ein Fehler auf, können wir mit connection.rollback() die gestartete Transaktion zurücksetzen.
Da ist es lohnenswert, eine Ausnahmebehandlung zu schreiben, und im catch
das rollback() einzusetzen.
HTBLA Kaindorf/Sulm
Seite 13 von 15
PUC | Datenbankzugriff mit JDBC
Folienvorschlag
Folienvorschlag
Grundlagen JDBC
Datenbanktreiber
Verbindung herstellen
Treiber anmelden
Verbindung aufbauen
Verbindung beenden
Datenbankabfragen
Statement-Objekt
executeQuery() und executeUpdate()
ResultSet-Objekt
SQLException
Prepared Statements
Transaktionen
HTBLA Kaindorf/Sulm
Seite 14 von 15
PUC | Datenbankzugriff mit JDBC
Zusammenfassung
Zusammenfassung
In diesem Skriptum wurden folgende Themen behandelt:
Die grundsätzliche Arbeitsweise und wichtige Architekturmerkmale von
JDBC.
Benötigte Treiber für den Zugriff auf die Datenbanken Interbase, MySQL
und Oracle.
Laden des JDBC-Treibers und Aufbau einer Datenbankverbindung.
Ausführen von Datenbankabfragen.
Ergebnisse eine Abfrage mit ResultSet ermitteln.
Änderungen an der Datenbank durchführen.
Behandlung von Ausnahmen bei der Datenabfrage.
Verwendung von vorbereiteten Anweisungen (Prepared Statements)
Verwendung von Transaktionen
Quellen
Ein Großteil der Informationen stammt aus dem Buch
"Java ist auch eine Insel" (2. Auflage) von Christian Ullenboom
welches als Openbook auf http://www.galileocomputing.de/katalog/openbook
zum freien Download zur Verfügung gestellt wird.
Weitere Quellen
Handbuch der Java-Programmierung, 3. Auflage (http://www.javabuch.de)
Sun Microsystems, Java Technologie Home Page (http://java.sun.com)
HTBLA Kaindorf/Sulm
Seite 15 von 15
Herunterladen