Previous Page TOC Index Next Page See Page

JBuilder-Datenbankarchitektur

Heute lernen Sie die Datenbankarchitektur des JBuilder kennen, die JDBC-Architektur sowie die Datenbankkomponenten-Hierarchie. Sie lernen Klassen und Schnittstellen kennen, die die Grundlagen für diese Architekturen bilden, und Sie sehen, was die einzelnen zu bieten haben. Insbesondere werden die folgenden Themen angesprochen:


Die datenbezogenen Komponenten des JBuilder befinden sich auf der Datenzugriff-Registerkarte der Komponentenpalette. Diese Registerkarte steht nur in den Versionen Professional (Pro) und Client/Server (C/S) von JBuilder zur Verfügung. Die JDBC-Klassen sind jedoch auch im JDK 1.1 enthalten, auch wenn Sie also die Standard-Version von JBuilder verwenden, ist ein Großteil der heute vorgestellten Informationen für Sie sinnvoll.

Datenbankgrundlagen

Bevor Sie die Datenbankarchitektur von JBuilder kennenlernen, sollten Sie einen Überblick über die Datenbankterminologie erhalten, ebenso wie einige Informationen über verschiedene Datenbankmodelle und -typen. Dieser Abschnitt dient als Einführung für die Leser, die noch nicht viel mit Datenbanken gearbeitet haben, und als Auffrischung für diejenigen, die schon lange nicht mehr mit Datenbanken gearbeitet haben. (Wenn Sie jeden Tag mit Datenbankentwicklung zu tun haben, können Sie diesen Abschnitt überblättern.)

Tabellen und Begriffe

Heute werden Sie mit Datenbankterminologie überschwemmt, deshalb wollen wir zunächst bestimmen, wie diese Begriffe in diesem Buch verwendet werden. Einige der Begriffe sind für JBuilder spezifisch, bei anderen handelt es sich um allgemeine Begriffe. Tabelle 1.41 bietet einen Überblick und eine kurze Erklärung.

Tabelle 14.1: Datenbankbegriffe

Begriff

Beschreibung

Client

Programm, das einen Zugriff anfordert.

Client/Server

Ein System, das seine Verarbeitung zwischen Client- und Server-Maschinen aufteilt.

Spalte

Ein Feld oder ein Attribut in einer Datenzeile.

Nebenläufigkeit

Die Möglichkeit, Prioritäten zuzuteilen und mehrere Zugriffsanforderungen zu verarbeiten

Datenzugriffssteuerung

Ein Steuerelement, das andere Steuerelemente mit Datenbanktabellen verbindet

Datenbezogenes Steuerelement

Ein Steuerelement, das Daten mit Hilfe von Datenzugriffs-Steuerelementen liest und ändert

Datenbank

Eine oder mehrere Tabellen mit Daten

DBMS

Datenbank Management System, wie etwa Sybase, Oracle oder InterBase

DBMS-Treiber

Eine ausführbare Datei, die eine Verbindung mit einer DBMS-Plattform einrichtet

Feld

Ein Datenabschnitt, etwa ein Name oder eine Kunden-ID

Multiuser

Die Möglichkeit, Nebenläufigkeit zu realisieren

Zeile

Ein einzelner Datensatz mit einer oder mehreren Spalten (Felder) mit Daten

SQL

Structured Query Language, eine Standard-Datenbankabfragesprache

Server

Programm, das Zugriff anbietet

Tabelle

Mehrere Zeilen (Datensätze) in einer Datenbank

Mit diesen Begriffsdefinitionen wollen wir jetzt verschiedene Datenbanktypen und Datenbankmodelle betrachten.

Datenbankmodelle

Es gibt viele Anwendungen, die Datenbanken verwenden, aber welches DatenDas relationale Modell

Die meisten der heute verwendeten Datenbanken sind relationale Datenbanken. Eine relationale Datenbank legt Informationen in logischen Tabellen ab, die sich aus Zeilen und Spalten zusammensetzen. Die Tabellen haben gemeinsame Spalten haben, die die Information aus einer Tabelle mit der einer anderen verknüpfen. Angenommen, Sie haben gerade ein Fotogeschäft eröffnet und Sie haben eine Tabelle mit Informationn über einen Kunden und eine Tabelle mit Informationen über Rechnungen. Nach dem ersten Monat könnten die beiden Tabellen etwa aussehen wie in Tabelle 14.2 und 14.3 gezeigt.

Tabelle 14.2: Kundentabelle

ID

Kunde

Stadt

Staat

ZipCode

2345

Diamond Head Photography

Honolulu

HI

96815

3458

Deep-Sea Cameras

Hilo

HI

96721

7857

Pretty as a Picture

Lahaina

HI

96761

Tabelle 14.3: Rechnungen

ID

Verkauf

Rechnung

Menge

Artikel

Preis

2345

19970404

19970531

1

34756

43.99

7857

19970406

19970531

2

38756

19.99

2345

19970412

19970531

1

14333

48.99

7857

19970414

19970531

2

38756

19.99

2345

19970416

19970531

10

38756

19.99

7857

19970423

19970531

2

32875

562.99

3458

19970428

19970531

7

12387

5.55

Sicher haben Sie das Prinzip erkannt. Diese beiden Tabellen werden über das Feld ID verknüpft, und hier handelt es sich um ein Beispiel einer Eins-zu-Viele-Beziehung. Mit anderen Worten, für jeden Datensatz in der Kunden-Tabelle können viele Datensätze in der Rechnungen-Tabelle existieren.

Flache Dateien

Anders als eine relationale Datenbank legt eine Datenbank mit flachen Dateien alle ihre Informationen in einem Datensatz ab. In dem obigen Beispiel beispielsweise gäbe es keine Kundentabelle, und die Rechnungstabelle würde für jeden Datensatz den Namen und die Adresse des Kunden beinhalten. Das ist natürlich eine enorme Platzverschwendung, weil die Information redundant ist. Aus diesem Grund werden heute hauptsächlich relationale Datenbanken eingesetzt.


Wenn Sie schon einmal den Begriff »Datenbank« verwendet haben, obwohl Sie eigentlich »Tabelle« meinten, dann stammt das aus der Zeit der Datenbanken der flachen Dateien, weil es dort nur eine Tabelle in einer Datenbank gab. Die Begriffe Datenbank und Tabelle wurden oft synonym verwendet. Das stimmt jedoch für relationale Tabellen nicht. In der relationalen Welt bilden verknüpfte Dateien eine Datenbank.

Datenbanktypen

Neben den beiden grundlegenden Datenbankmodellen gibt es auch noch verschiedene Datenbanktypen, die Sie einsetzen können. Auch hier hängt die Entscheidung davon ab, welche Art Anwendung Sie entwickeln und wie sie eingesetzt werden soll.

Standalone

Eine Standalone-Datenbank legt ihre Dateien in dem lokalen Dateisystem ab und das Programm, das darauf zugreift, befindet sich ebenfalls auf derselben Maschine. Dieser Datenbanktyp kann für Java-Programme geeignet sein, die für den Einbenutzer-Zugriff vorgesehen sind. Das bedeutet, nur eine Person (diejenige, die die lokale Maschine benutzt) greift auf die Daten zu. Das ist das einfachste Szenario, weil Sie sich keine Gedanken um Mehrbenutzerzugriff (Nebenläufigkeit), Netzwerkverkehr oder Client/Server-Aspekte kümmern müssen. Wenn Sie beispielsweise ein Programm schreiben wollen, das Ihre persönlichen Ausgaben verwaltet und nicht vorhaben, diese Information jemandem anderen zur Verfügung zu stellen, ist eine Standalone-Datenbananwendung für Ihre Bedürfnisse geeignet.

Gemeinsam genutzte Dateien

Eine Datenbank mit gemeinsam genutzten Dateien ist eine verteilte Form einer Datenbank, die mehreren Anwendern Zugriff auf dieselben Dateien bietet. Im allgemeinen haben die Anwender ein Programm für den Zugriff auf die Tabellen auf ihrer lokalen Maschine im Netzwerk, und die Datenbank wird auf einer zentralen Maschine vorgehalten. Um welche Art Netzwerk es sich handelt, ist unwesentlich, weil die lokale Maschine auf die Datenbank als gemeinsam genutzte Datei im Netzwerk zugreift. Wenn ein Anwender auf die Datei zugreift, wird diese gesperrt, bis der Anwender die Abfrage, Aktualisierung oder eine andere Verarbeitung abgeschlossen hat. Jeder Anwender muß also warten, bis er Zugriff auf die Datei erhält, diese Lösung ist also nur geeignet, wenn nicht viele Anwender auf die Tabellen der Datenbank zugreifen.

Client/Server

Eine Client/Server-Datenbank (auch als Two-Tier-System bezeichnet) wurde so optimiert, daß sie viele gleichzeitige Anfragen verarbeiten kann. Ein Teil der Verarbeitung erfolgt auf der lokalen Maschine (Client), ein Teil auf der zentralen Maschine (Server). Dabei kann zwar immer noch nur jeweils ein Zugriff auf die Datei erfolgen, aber der Client kann etwas anderes tun, während der Server die Anfrage bearbeitet (via SQL-Abfragen oder gespeicherte Prozeduren). Andere Clients können ihre Anforderungen in Warteschlangen einreihen und werden nicht aufgrund gesperrter Tabellen abgewiesen.

Wieviel Verarbeitung passiert auf dem Client, wieviel auf dem Server? Das ist ein Balanceakt, der detaillierte Planung erforderlich macht, wobei die Anzahl der potentiellen Benutzer, der Netzwerkverkehr, die Anforderungstypen und ihre Häufigkeit sowie andere Aspekte berücksichtigt werden müssen. Außerdem ist für Client/Server-Systeme ein Protokoll erforderlich, wie etwa TCP/IP, wodurch zusätzliche Konfigurationen und administrative Aufgaben anfallen. Client/Server ist zwar in der Regel eine aufwendigere Lösung, aber wenn es viele gleichzeitige Anwender gibt, ist sie wahrscheinlich am besten für Sie geeignet.

Multi-Tier

Multi-Tier-Systeme sind Client/Server-Systeme, die die Verarbeitung noch weiter aufsplitten, wozu sie manchmal eine Zwischenschicht einführen, die sogenannten »Middleware«, die zusätzliche Verarbeitungen vornimmt und die Last vom Server abzieht. Dadurch kann der Server mehr Anforderungen verarbeiten, und die Kapazität und der Durchsatz steigen. Die Middleware ist in der Regel multithreaded, um mehrere gleichzeitige Anfragen verarbeiten zu können, und sie kann so konfiguriert werden, daß Anfragen für verschiedene Datenbanken verarbeitet werden.

JDBC-Architektur

JDBC eröffnet uns eine ganz neue Welt in der Client/Server-Technologie. Wenn Sie dachten, die Client/Server-Konfiguration auf dem lokalen Netzwerk war anspruchsvoll, können Sie jetzt mit Clients und Servern arbeiten, die meilenweit voneinander entfernt sind, und Sie müssen auch den Verkehr auf dem Internet berücksichtigen!


JDBC ist ein JavaSoft-Warenzeichen und keine Abkürzung. Häufig wird es als Java DataBase Connectivty übersetzt. JDBC ist JavaSoft's Standard-API, das SQL-Anweisungen für den Zugriff auf Datenbanken in Java-Programmen verwendet.
JDBC klingt vielleicht vertraut, wenn Sie es schon mit ODBC zu tun hatten. ODBC ist die Open Database Connectivity, ein Standard, den Microsoft eingeführt hat, um eine Möglichkeit zu bieten, auf die verschiedenen Datenbanken zuzugreifen, die in einem einzigen API existieren können. Warum verwendet also Java nicht einfach ODBC? Der wichtigste Grund ist, daß ODBC C-bezogen ist und zahlreiche Zeiger verwendet. Darüber hinaus wurde ODBC hauptsächlich für Microsoft-Plattformen entwickelt. Das Java-Team wollte seine Ziele beibehalten (Einfachheit, Robustheit und Portabilität) und entscheid, ein API zu entwickeln, das mit allen Datenbanken arbeiten sollte, egal, welche Sprache ihre Plattform verwendet.

Wie ODBC basiert auch JDBC auf dem X/Open SQL CLI (Call Level Interface), aber im Gegensatz zu ODBC handelt es sich bei JDBC um ein Java-API, das plattformunabhängig und herstellerneutral ist. Das JDBC-API verwendet SQL SQL (Structured Query Language) für den Datenzugriff über das Internet und kann somit auf fast alle Daten zugreifen, die Ihre Anwendung braucht. JDBC ist ebenfalls objektorientiert und deshalb einfacher zu lernen und zu implementieren. Und schließlich unterstützt JDBC Client/Server- und Multi-Tier-Systeme.

Verwendung von JDBC in Applets

Applets haben den Sprung ins Internet geschafft, und so wie es Sicherheitsprobleme bei Applets gibt, gibt es sie beim Datenbankzugriff über das Internet. In diesem Abschnitt erfahren Sie etwas über die Prozesse, die Aspekte und einige der Sicherheitsprobleme, die mit JDBC gelöst werden können.

Wenn Sie ein Applet mit Zugriff auf eine Datenbank über das Internet entwickeln, gibt es einige offensichtliche Sicherheitsprobleme. Wie Sie in der 1. Woche gelernt haben, sind Java-Applets zahlreichen Einschränkungen unterworfen, vom Zugriff auf die Festplatte des Clients bis hin zu Netzwerkverbindungen zu anderen als dem eigenen Server. Häufig sind die Daten der wichtigste Besitz eines Unternehmens, wenn man also den Datenbankzugriff über das Internet in Betracht zieht, dann potenzieren sich die Sicherheitsprobleme. Wie kann JDBC diese Probleme lösen?

JDBC erlaubt keinen unzuverlässigen (d.h. über das Internet heruntergeladenen) JDBC-fähigen Applets, auf die Daten einer lokalen Datenbank zuzugreifen. Das JDBC-Applet kann nur eine Verbindung zu einer Datenbank einrichten, die sich auf dem Server befindet, von dem es geladen wurde. Wenn das Applet jedoch durch die Java-VM als zuverlässig eingestuft wird (etwa durch Verwendung eines codierten Paßworts, oder wenn der Client davon ausgeht, daß Applets von einer bestimmten Site als sicher betrachtet werden können), wird das Applet wie eine Anwendung behandelt, was die Sicherheit betrifft.

Verwendung von JDBC in Anwendungen

Java-Anwendungen werden auch für andere Aufgaben als den Einsatz im Internet verwendet. Es gibt immer mehr Firmen-Intranets und -Extranets, und der Zugriff, den JDBC bietet, ist mit eine Ursache für ihre schnelle Verbreitung.


Ein Intranet ist ein Netzwerk, das die Internet-basierte Technologie nutzt, um Zugriff auf Firmendaten bereitzustellen, und das lokale Netzwerke (LANs), Weitverkehrsnetze (WANs) und entfernt gelegenen Zugriff (über Modems oder ISDN-Leitungen) umfassen kann. Im wesentlichen handelt es sich bei einem Intranet um eine private Version des Internet, wo Zugriff von Clients auf verschiedenen Plattformen erlaubt ist.


Ein Extranet ist ein Intranet, das so erweitert wurde, daß es auch die Geschäftspartner der Firma berücksichtigt, etwa Lieferanten und Kunden. Ein Extranet verbindet mehrere Firmen mit gemeinsamen Interessen und Daten, die gemeinsam genutzt werden sollen.
Anders als Groupware verwenden Intranets und Extranets die allpräsenten Web-Browser als vertraute Benutzeroberfläche, die nur wenig Übung erforderlich macht und alle möglichen Daten anzeigt, ohne ein ganz bestimmtes Format vorzuschreiben. Außerdem können Die Anwender auf Daten zugreifen, die auf Windows-, Macintosh- oder UNIX-Maschinen bereitgestellt werden. Kein Wunder, daß diese Technologie immer beliebter wird.

Aufgrund der Firewall-Technologie ist die Sicherheit bei Java-Anwendungen kein großes Thema. Anwendungen, die lokal geladen werden, werden als zuverlässig betrachtet. Eine andere Lösung ist die Verwendung eines Multi-Tier-Systems, wo die Middleware für die Sicherheit und den Zugriff verantwortlich ist, und als Sicherheitsgarant zwischen Client und Server steht. Wie Sie gleich sehen werden, unterstützt JDBC alle diese Sicherheits-Strategien.

Database Connectivity

JDBC unterstützt unter anderem Informix, InterBase, MS SQL Server, Oracle, Paradox, Sybase und xBase. Diese Unterstützung wird durch vier Arten der Verbindung realisiert:

Die beiden letzten Protokoll-Lösungen werden von JavaSoft als die bevorzugte Weise des Datenbankzugriffs mit JDBC empfohlen.


Die neuesten Informationen von JavaSoft über die JDBC-Treiber finden Sie unter der Adresse http://www.javasoft.com/products/jdbc.

Andere Verbindungen

Es gibt noch zwei Arten von Verbindungen, die erwähnt werden sollen, RMI und CORBA.

RMI steht für Remote Method Invocation und ist eine Methode, wie eine Java-Client-Anwendung direkt Methoden für ein Java-Objekt auf einem entfernt gelegenen Server ausführen kann. Mit Hilfe der Serialisierung und Deserialisierung zum Speichern und Wiederherstellen des Objektstatus erlaubt dieses Modell eine reine Java-Lösung für den Datenbankzugriff, weil die RMI-Klassen Teil des JDK sind.

CORBA steht für Common Object Request Broker Architecture und ist ein Standard der Object Management Group. Dieser Standard definiert die IDL (Interface Definition Language), die ein »Abkommen« zwischen Client- und Server-Implementierung aushandelt. JavaSoft arbeitet gerade an einem IDL-Compiler.

JDBC-Klassen

Um zu verstehen, wie JDBC funktioniert, wollen wir die Schnittstellen und Klassen betrachten, aus denen es sich zusammensetzt, die alle im Paket java.sql enthalten sind. (Vergessen Sie nicht, dieses Paket in Ihren Code zu importieren, wenn Sie diese Klassen verwenden.) Das Laden von Daten mit Hilfe von JDBC basiert auf vier sehr einfachen Schritten.

Der erste Schritt wird normalerweise automatisch vom DriverManager ausgeführt, den wir als nächstes betrachten.


Dieser Abschnitt stellt keine detaillierte Beschreibung der JDBC-Methoden dar, sondern soll nur die wichtigsten davon vorstellen. Genauere Informationen finden Sie in der Online-Hilfe.

DriverManager

Die Klasse DriverManager enthält zahlreiche Methoden zur Verwaltung, Registrierung und Deregistrierung von Treibern. Größtenteils brauchen Sie jedoch nur die Methode getConnection() aufzurufen, dann lädt der DriverManager automatisch den geeigneten Treiber für die Datenbank. Tabelle 14.4 bietet einen Überblick über die wichtigsten Methoden dieser Klasse.

Tabelle 14.4: Methoden der Klasse DriverManager

Methodensignatur

Überblick

deregisterDriver(Driver)

Entfernt den angegebenen Treiber aus der Liste der registrierten Treiber

getConnection(String)

Gibt eine Verbindung zu der Datenbank an der im String-Argument spezifizierten URL zurück

getConnection(String, Properties)

Gibt eine Verbindung zu der an der URL befindlichen Datenbank zurück wobei die Information im Properties-Argument spezifiziert wird

getConnection(String, String, String)

Gibt eine Verbindung zu der an der URL (erster String) befindlichen Datenbank zurück und nimmt eine Anmeldung mit dem angegebenen Login und Paßwort (die beiden nächsten String-Argumente) vor.

getDrivers()

Listet die verfügbaren Treiber auf

registerDriver(Driver)

Fügt den angegebenen Treiber in die Liste der Treiber ein

Die Methoden registerDriver() und deregisterDriver() erlauben der aufrufenden Klasse, Treiber in die Treiberliste des Klassen-Loaders einzutragen oder daraus zu entfernen. getDrivers() gibt eine Liste aller Treiber zurück.

Die überladene getConnection()-Methode bietet Ihnen mehrere Möglichkeiten, die Verbindung einzurichten. Alle drei benötigen eine URL. Für Datenbanken kann sich die URL-Syntax von dem unterscheiden, was Sie gewöhnt sind. Das grundsätzliche Format sieht wie folgt aus:

protokoll:unterprotokoll:untername

Die gebräuchlichsten Protokolle sind http: und ftp:, und die Unternamen sehen normalerweise aus wie //www.microsoft.com/ oder //www.javasoft.com/. Bei der Verwendung von JDBC ist das protokoll jdbc:, das unterprotokoll stellt einen bestimmten Datenbankmechanismus dar, und der Untername ist die Information, die für die Verbindung zu der Datenbank benötigt wird (inklusive Port). Hier einige typische JDBC-URLs:

jdbc:odbc:mydata
jdbc:odbc:mydata;UID=mylogin;PWD=mypasswd
jdbc:dbprot://testsite:321/mytables/mydata

Das erste Beispiel zeigt, wie eine Verbindung zu der Datenbank mydata eingerichtet wird, wozu über das odbc-Unterprotokoll die JDBC-ODBC-Bridge verwendet wird. Das zweite Beispiel zeigt dieselbe Verbindung mit ODBC-Login (UID) und Paßwort (PWD). Das dritte Beispiel zeigt, wie ein Datenbank-Unterprotokoll (dbprot:) verwendet wird, um sich auf Port :321 auf der Web-Seite testsite anzumelden, wobei sich die Datenbank mydata im Verzeichnis mytables befindet.

Um die Methode getConnection() zu verwenden, weisen Sie einfach einer String-Variablen die entsprechende URL zu und rufen damit die Methode auf.

String myURL = ("jdbc:dbprot://testsite:321/mytables/mydata");
getConnection(myURL, "myUID", "myPWD");


In URLs wird in Pfadnamen der Schrägstring (/) verwendet, das ist der Standard im World Wide Web. Windows-Plattformen verwenden den Backslash (\), aber JBuilder erlaubt im Java-Code ebenfalls die Verwendung des Schrägstrichs (/), Sie müssen also die URLs nicht ändern, wenn Ihr Code im Internet funktionieren soll.

Nachdem Sie eine erfolgreiche Verbindung eingerichtet haben, wird ein Connection-Objekt zurückgegeben. Hier eine Codezeile, die zeigt, wie das realisiert wird:

Connection dbConn = DriverManager.getConnection
("jdbc:odbc:dbname", "mylogin", "mypasswd");

Als nächstes betrachten wir die Connection-Schnittstelle.

Connection

Eine Klasse, die die Schnittstelle java.sql.Connection implementiert, kann Methoden zum Sperren von Tabellen, zum Commit und Rollback von Änderungen und zum Schließen von Verbindungen überschreiben. Außerdem bietet sie Methoden zur Vorbereitung bestimmter Aufrufe und Anweisungen. Tabelle 14.5 bietet einen Überblick über einige der wichtigsten Methoden der Schnittstelle.

Tabelle 14.5: Die Methoden der Schnittstelle java.sql.Connection

Methodensignatur

Beschreibung

close()

Bietet eine Möglichkeit, die Connection sofort zu schließen und die JDBC-Ressourcen freizugeben.

commit()

Aktualisiert die Tabelle mit allen Änderungen, die seit dem letzten Commit/Rollback vorgenommen wurden, und gibt die Connection-Sperren für die Datenbank frei.

createStatement()

Gbit ein neues Statement-Objekt zurück.

getAutoCommit()

Gibt einen Booleschen Wert zurück: true, wenn AutoCommit aktiviert ist, false, wenn es deaktiviert ist.

getMetaData()

Gibt ein DatabaseMetaData-Objekt zurück, das Informationen über die Tabellen, die gespeicherten Prozeduren und die unterstützte SQL-Grammatik für die aktuelle Connection-Datenbank enthält.

isClosed()

Gibt einen Booleschen Wert zurück: true, wenn die Connection geschlossen ist, false, wenn sie geöffnet ist.

prepareCall(String)

Gibt ein neues CallableStatement-Objekt mit optionalen OUT- oder INOUT-Parametern zurück. Das String-Argument ist eine SQL-Anweisung.

prepareStatement(String)

Gibt ein neues PreparedStatement-Objekt zurück, das eine vorkompilierte einfache SQL-Anweisung oder eine mit IN-Parametern. Das String-Argument ist eine SQL-Anweisung.

rollback()

Verwirft alle Änderungen, die seit dem letzten Commit/Rollback in der Tabelle vorgenommen wurden; alle Connection-Sperren werden freigegeben.

setAutoCommit(boolean)

Setzt das Boolesche Argument auf true, um AutoCommit zu aktivieren, auf false, um es zu deaktivieren.

Statement

Die Klasse, die die Statement-Schnittstelle implementiert, kann Methoden überschreiben, die Ihnen ermöglichen, unterschiedliche SQL-Anweisung zu verwalten und auszuführen. Tabelle 14.6 bietet einen Überblick über die gebräuchlichsten Methoden.

Tabelle 14.6: Die Methoden der Schnittstelle java.sql.Statement

Methodensignatur

Beschreibung

cancel()

Bricht eine Anweisung ab, die in einem anderen Thread ausgeführt wird.

close()

Bietet eine Möglichkeit, die Connection zu schließen und JDBC-Ressourcen freizugeben.

execute(String)

Führt die im String-Argument angegebene SQL-Anweisung aus; gibt true zurück, wenn es sich beim ersten Ergebnis um ein ResultSet handelt, false, wenn das Ergebnis ein int ist.

executeQuery(String)

Führt die im String-Argument angegebene SQL-Anweisung aus; gibt das ResultSet mit den Abfrageergebnissen zurück.

executeUpdate(String)

Führt die SQL-Anweisungen UPDATE, INSERT, DELETE aus, oder Anweisungen, die nichts zurückgeben (wie etwa die DDL-Anweisung), die im String-Argument angegeben sind; gibt einen Integer zurück, der die Anzahl der Zeilen darstellt, die beteiligt waren (0 für Anweisungen ohne Rückgabe).

getCursorName()

Gibt einen String zurück, der die ID der aktuellen Zeile enthält (durch eine UPDATE- oder DELETE-Anweisung gesetzt)

getMoreResults()

Gibt true zurück, wenn das nächste Ergebnis ein ResultSet ist, false, wenn es ein Integer ist.

getQueryTimeout()

Gibt einen Integer zurück, der die Anzahl der Sekunden darstellt, die ein Treiber darauf wartet, daß die SQL-Anweisung ausgeführt wird.

getResultSet()

Gibt ein ResultSet zurück, wenn es aktuelle Ergebnisse gibt. Wenn keine weiteren Ergebnisse oder ein Aktualisierungszähler vorliegen, wird null zurückgegeben.

setCursorName(String)

Setzt die ID der aktuellen Zeile (durch eine UPDATE- oder DELETE-Anweisung erzeugt) auf das String-Argument.

setQueryTimeout(int)

Setzt die Anzahl der Sekunden die ein Treiber wartet, bis eine SQL-Anweisung ausgeführt wird.

Es gibt noch viele andere Methoden in der Statement-Schnittstelle. Weitere Informationen entnehmen Sie bitte der Online-Hilfe.


SQL bietet die Möglichkeit, mit einer Datenbank zu kommunizieren. Eine vollständige Beschreibung von SQL würde über den Rahmen dieses Buchs hinausgehen, aber es in dem Buch SQL in 14 Tagen von SAMS finden Sie eine ausgezeichnete Einführung in SQL.

Neben der Statement-Schnittstelle gibt es noch zwei weitere Schnittstellen, die hier erwähnt werden sollen. Die Schnittstelle CallableStatement erbt von der Schnittstelle PreparedStatement, die wiederum von der Statement-Schnittstelle erbt. Auf jeder Ebene werden zusätzliche abstrakte Methoden für den jeweiligen SQL-Anweisungstyp bereitgestellt.

Die Schnittstelle PreparedStatement wird verwendet, wenn Sie eine einfache SQL-Anweisung vorkompilieren wollen, um sie mehrere Male auszuführen, oder wenn die SQL-Anweisung IN-Parameter hat und vorkompiliert werden muß. Das ist eine effizientere Weise, die Anweisung auszuführen.

Die Schnittstelle CallableStatement ist in der Regel eine vorkompilierte gespeicherte Prozedur, die von gespeicherten Datenbankprozeduren mit OUT- oder INOUT-Parametern verwendet werden muß.

Hier folgt ein typischer Codeabschnitt für die Abfrage von myTable:

Connection dbConn = DriverManager.getConnection
("jdbc:odbc:dbname", "mylogin", "mypasswd");
Statement sqlStmt = dbConn.createStatement();
ResultSet rSet = sqlStmt.executeQuery
("SELECT xInt, yString FROM myTable");

Dieses Beispiel verwendet die Connection-Instanz dbConn und erzeugt die Statement-Instanz sqlStmt. Mit sqlStmt führt es die SQL-Abfrage unter Verwendung der Methode executeQuery() von Statement aus und gibt die ResultSet-Instanz rSet zurück. Die abstract-Klasse von ResultSet ist der letzte Teil der JDBC-Architektur, den Sie als nächsten kennenlernen werden.

ResultSet

Die Implementierung der Methoden der abstrakten Klasse java.sql.ResultSet steuern den Zugriff auf die Zeilenergebnisse aus einer vorgegebenen SQL-Anweisung. Durch diese Klasse erhalten Sie Zugriff auf die Ergebnisse all Ihrer Abfragen. Tabelle 14.7 zeigt einige der wichtigsten Methoden dieser Schnittstelle.

Tabelle 14.7: abstract-Methoden von java.sql.ResultSet abstract

Methodensignatur

Beschreibung

close()

Ermöglicht, die Connection unmittelbar zu schließen und die JDBC-Ressourcen freizugeben.

findColumn(String)

Gibt einen Integer zurück, der dem Spaltenindex für den Spaltennamen im String-Argument zurückgibt.

getAsciiStream(int)

Gibt einen InputStream mit den ASCII-Werten des LONGVARCHAR-Wert aus der aktuellen Zeile zurück; das int-Argument ist der Spaltenindex.

getAsciiStream(String)

Gibt einen InputStream mit dem ASCII-Wert aus dem LONGVARCHAR-Wert der aktuellen Zeile zurück; das String-Argument ist der Spaltenname.

getBinaryStream(int)

Gibt einen InputStream mit dem ASCII-Wert aus dem LONGVARCHAR-Wert der aktuellen Zeile zurück; das int-Argument ist der Spaltenname.

getBinaryStream(String)

Gibt einen InputStream mit dem ASCII-Wert aus dem LONGVARBINARY-Wert der aktuellen Zeile zurück; das String-Argument ist der Spaltenname.

getCursorName()

Gibt einen String mit der ID der aktuellen Zeile zurück (gesetzt durch UPDATE oder DELETE).

getMetaData()

Gibt ein ResultSetMetaData-Objekt mit der Anzahl der Spalten, den Datentypen und anderen Eigenschaften der Zeilen im aktuellen ResultSet zurück.

getUnicodeStream(int)

Gibt einen InputStream mit dem ASCII-Wert aus dem LONGVARCHAR-Wert der aktuellen Zeile zurück; das String-Argument ist der Spaltenname.

getUnicodeStream(String)

Gibt einen InputStream mit dem ASCII-Wert aus dem LONGVARCHAR-Wert der aktuellen Zeile zurück; das String-Argument ist der Spaltenname.

getXxxx(int)

Gibt einen Datentyp zurück, der durch Xxxx repräsentiert wird (z.B. int, long, String, Object, usw.), und der den Wert der aktuellen Zeile enthält. Das int-Argument ist der Spaltenindex.

getXxxx(String)

Gibt einen Datentyp zurück, der durch Xxxx repräsentiert wird (z.B. int, long, String, Object, usw.), und der den Wert der aktuellen Zeile enthält. Das String-Argument ist der Spaltenname.

setCursorName(String)

Setzt die ID der aktuellen Zeile (durch UPDATE oder DELETE gesetzt) auf das String-Argument.

next()

Gibt true zurück, wenn die nächste Zeile gültig ist, andernfalls false.

wasNull()

Gibt true zurück, wenn der gelesene Wert null war, false andernfalls.

Es gibt zwei getXxxx()-Methoden für jeden Java-Typ; eine, die einen Spaltenindex verwendet, und eine, die einen Spaltennamen verwendet. Um beispielsweise ein String-Objekt aus der zweite Spalte der aktuellen Zeile zu ermitteln, schreiben Sie folgendes:

getString(2);

Damit erhalten Sie den Wert dieses Feldes als Java-String-Objekt zurück. Um einen Zeichen-Wert aus der Spalte Gender zu ermitteln, würden Sie folgendes schreiben:

getChar(Gender);


Anders als Java-Indizes beginnen SQL-Spaltenindizes mit 1, nicht mit 0. Seien Sie also vorsichtig! Außerdem wird bei den SQL-Spaltennamen die Groß-/Kleinschreibung nicht berücksichtigt. Wenn Sie Spaltennamen verwenden, um auf Felder in der aktuellen Zeile zuzugreifen, kann es aufgrund dieser Nichtberücksichtigung der Groß-/Kleinschreibung mehrere Spalten mit demselben Namen geben. Wenn das passiert, wird der erste übereinstimmende Spaltenname verwendet.

Die Methode findColumn() gbit die Spaltennummer für einen Spaltennamen zurück.

Der Cursor in einer ResultSet wird unmittelbar vor der ersten Zeile positioniert, wenn das ResultSet erzeugt wird. Um den Cursor durch das ResultSet zu bewegen, rufen Sie die Methode next() auf. Bevor Sie versuchen, die Daten in die Zeile einzulesen, sollten Sie den Rückgabewert von next() auswerten, um festzustellen, ob Sie auf einer gültigen Zeile gelandet sind, oder ob es keine weiteren gültigen Zeilen gibt. Der folgende Code kombiniert die oben gezeigten Codeausschnitte mit Hilfe einer while-Schleife, die das ResultSet rSet durchläuft:

Connection dbConn = DriverManager.getConnection
("jdbc:odbc:dbname", "mylogin", "mypasswd");
Statement sqlStmt = dbConn.createStatement();
ResultSet rSet = sqlStmt.executeQuery
("SELECT xInt, yString FROM myTable");
while (rSet.next()) {
int xIntVal = getInt("xInt");
String yStrVal = getString("yStr");
}

Die Methode getMetaData() gibt ein ResultSetMetaData-Objekt zurück, das Informationen über das ResultSet enthält, etwa die Anzahl der Spalten. Außerdem gibt sie Informationen über einzelne Spalten (Felder) zurück, etwa den Namen, den Titel, die maximale Breite, die Datentypen, die Genauigkeit (Dezimalstellen), die Skalierung (Dezimalpunkte) und anderes. Eine vollständige Liste aller Methoden der Klasse ResultSetMetaData, die Informationen über das ResultSetMetaData-Objekt zurückgeben, finden Sie in der Online-Hilfe.

Typabbildungen

Einfach ausgedrückt, es gibt Datentypen, die spezifisch für SQL sind, und die auf Java-Datentypen abgebildet werden müssen, wenn Sie erwarten, daß Java sie verarbeitet. Diese Umwandlung kann in drei Kategorien eingeteilt werden:


Verwechseln Sie java.sql.Date für die Konvertierung von SQL-DATE-Information nicht mit dem internen java.util.Date, das als Java-Date-Objekt verwendet wird. Das letztere akzeptiert kein SQL-DATA-Feld.

Es gibt Tabelle in der Online-Hilfe, die die Konvertierungen in beide Richtungen genau beschreiben (von SQL in Java und von Java in SQL).

Die Datentypen DECIMAL und NUMERIC müssen unter Verwendung einer speziellen Klasse konvertiert werden, weil die absolute Genauigkeit eingehalten werden muß. Vor JDBC gab es keine Datentypen für das, was benötigt wurde. Das JDBC-API enthält die Klasse java.sql.Numeric, die Ihnen ermöglicht, die SQL-Werte DECIMAL und NUMERIC in Java umzuwandeln.

Das SQL-DATE besteht aus Tag, Monat und Jahr, TIME aus Stunden, Minuten und Sekunden. TIMESTAMP kombiniert DATE und TIME und führt ein Feld für die Nanosekunden ein. Weil java.util.Date keine 1:1-Entsprechung mit diesen SQL-Typen bietet, wurde die Klasse java.sql.Date definiert, die die SQL-Werte DATE und TIME verarbeitet, während java.sql.Timestamp so definiert ist, daß es SQL-TIMESTAMP verarbeitet.

Ein JDBC-API-Beispiel

Basierend auf den früheren Beispielen finden Sie im folgenden ein vollständiges Listing, wo eine typische JDBC-Verbindung eingerichtet, eine Datenbank abgefragt, Ergebnisse aus einem ResultSet ermittelt und die Daten ausgedruckt werden. Das Programm in Listing 14.1 ist zwar nicht direkt ausführbar (es sei denn, Sie haben die Tabelle myTable mit den entsprechenden Daten vorliegen), aber es soll Ihnen zeigen, wie ein Programm aussieht, das das JDBC-API verwendet.

Listing 14.1: QueryMyTable.java

1: import java.net.URL;
2: import java.sql.*;
3:
4: public class QueryMyTable {
5:
6: public static void main(String args[]) {
7:
8: try {
9:
10: // Verbindung zur Datenbank einrichten
11: String theUrl = "jdbc:odbc:dbname";
12: Connection dbConn = DriverManager.getConnection
13: (theUrl, "mylogin", "mypasswd");
14:
15: // SELECT-Anweisung ausführen
16: Statement sqlStmt = dbConn.createStatement();
17: ResultSet rSet = sqlStmt.executeQuery
18: ("SELECT xInt, yString FROM myTable");
19:
20: // Ergebniszeilen durchlaufen und die ermittelten
21: // Werte ausgeben
22: System.out.println("Return results");
23: while (rSet.next()) {
24: int xIntVal = rSet.getInt("xInt");
25: String yStrVal = rSet.getString("yStr");
26: System.out.print("xIntVal = " + xIntVal);
27: System.out.print("yStrVal = " + yStrVal);
28: System.out.print("/n");
29: }
30:
31: sqlStmt.close();
32: dbConn.close();
33: }
34:
35: catch (Exception e) {
36: System.out.println("EXCEPTION: " + e.getMessage());
37: }
38:
39: }
40:
41: }


Ein Großteil dieses Codes sollte Ihnen bereits vertraut sein. Es gibt jedoch einige Dinge, die erklärt werden sollen:


Jetzt wollen wir die datenbezogenen Komponenten betrachten, die Ihnen der JBuilder bereitstellt.

JBCL und DataBroker

In JBuilder geht der DataBroker-Zugriff für den Datenzugriff und die Aktualisierung von JDBC-Datenquellen in drei Phasen vor:

Mögliche Konflikte bei der Bearbeitung werden automatisch behandelt. Dieser Ansatz, der in der DataBroker-Architektur implementiert ist, ermöglicht Ihnen einen Datenzugriff auf sehr hoher Ebene, wozu Sie Drag&Drop-Komponenten nutzen und mit den JBCL-Komponenten Ihrer Benutzeroberfläche verbinden können.


Eine Datenzugriffs-Komponente bietet Ihnen die Möglichkeit, (über Eigenschaften) eine Verbindung zu einer Datenquelle herzustellen, etwa zu einer Datenbank.


Eine datenbezogene Komponente kann unter Verwendung einer Datenzugriffs-Komponente als »Kanal« Daten entgegennehmen.

Die DataBroker-Architektur basiert auf der DataSet-Klassenhierarchie im JBCL. Damit Sind Sie in der Lage bereits ausgetestet Komponenten zu verwenden und durch Setzen ihrer Eigenschaften und Einführen von Ereignis-Handlern Ihren Bedürfnissen anzupassen. Diese Architektur beinhaltet Resolver- und DataFile-Schnittstellen (die Sie später noch kennenlernen werden). Abbildung 14.1 zeigt die DataBroker-Architektur.

Abbildung 14.1: Die DataBroker-Architektur von JBuilder

Die Klassen DataSet und StorageDataSet sind abstrakt, während DataSetView, QueryDataSet, ProcedureDataSet, TableDataSet und TextDataFile Komponenten auf der Datenzugriff-Registerkarte der Komponentenpalette sind. Abbildung 14.2 zeigt die Datenzugriff-Registerkarte.

Abbildung 14.2: Die Datenzugriff-Registerkarte in der Komponentenpalette

Für die Registry-Einstellungen ist für einen Java-JDBC-Treiber keine spezielle Installation erforderlich. Dadurch können Anwendungen, die mit dem DataBroker erzeugt werden, als Anwendung oder als Applet ausgeführt werden.

Der DataBroker nimmt die Typabbildung mit Hilfe von Variant-Typen vor. Variant ist eine Klasse, die statische int-Bezeichner hat, die die unterstützten Datentypen auflisten. Größtenteils erfolgt die Zuordnung von JDBC-Typen zu Variant-Typen 1:1. Sie ist in der JBCL-Referenz dokumentiert.

Alle DataBroker-Ausnahmeklassen für die Fehlerbehandlung sind entweder DataSetException oder eine Unterklasse davon. DataBroker-Ausnahmen können andere Aunahmetypen auffangen (wie etwa IOException und SQLException).

Datenzugriff

Jetzt betrachten wir die einzelnen Klassen und Komponenten, die Sie zum Erzeugen von Datenbankanwendungen in JBuilder brauchen.

DataSet

DataSet ist eine abstrakte Klasse. Sie stellt alle Methoden zur Navigation, für den Datenzugriff und die Aktualisierung von DataSets bereit. Außerdem unterstützt sie Master-Detail-Beziehungen, Sortieren und Filtern. Datenbezogene JBCL-Steuerelemente haben eine DataSet-Eigenschaft, die sie auf eine beliebige von DataSet abgeleitete Komponente setzen können, wie etwa DataSetView, QueryDataSet, ProcedureDataSet, and TableDataSet.

StorageDataSet

StorageDataSet ist eine abstrakte Klasse, die das Speichern von DataSet-Daten und die Bereitstellung von Indizes erlaubt. Sie stellt Methoden zum Hinzufügen, Löschen, Änderung und Verschieben von Daten bereit. Außerdem werden hier Aktualisierungen, Einfügungen und Löschvorgänge automatisch aufgezeichnet.

DataSetView

DataSetView stellt einen Cursor mit Sortierung und Filtermöglichkeit bereit, indem die StorageDataSet-Eigenschaft entsprechend gesetzt wird. Sie können diese Komponente auch verwenden, um mehrere DataSetView-Komponenten zu einem neuen DataSet zusammenzusetzen, indem Sie ihre StorageDataSet-Eigenschaften ändern.

QueryDataSet

QueryDataSet ist eine JDBC-spezifische Unterklasse von DataSet, die einen JDBC-Datenprovider verwaltet, der in der Query-Eigenschaft (eine SQL-Anweisung) angegeben ist.

ProcedureDataSet

ProcedureDataSet (nur C/S) ist ebenfalls eine JDBC-spezifische Unterklasse von DataSet, die einen JDBC-Datenprovider verwaltet, der in der Procedure-Eigenschaft (eine gespeicherte Prozedur) angegeben ist.

QueryResolver

Ein QueryResolver steuert, wie Aktualisierungen erfolgen und wie Konflikte aufgelöst werden. Dazu wird die Resolver-Eigenschaft Ihrer DataSet-Komponente auf Ihre QueryResolver-Komponente gesetzt.

TableDataSet

TableDataSet ist eine DataSet-Komponente ohne eingebauten Provider, sie kann aber ihre Änderungen zurück in eine Datenquelle schreiben.

DataModule

Das DataModule ist ein nicht-visueller Container für Komponenten wie etwa DataSet oder Database und steht in der Object Gallery (Datei | Neu) zur Verfügung. Auch andere Container können Datenzugriff-Komponenten enthalten, wie etwa Frames oder Applets, aber es ist besser, sie in einem DataModule abzulegen. Dadurch können Sie eine von Ihren Benutzeroberflächen-Komponenten separate Anwendungslogik bereitstellen. Wenn Sie die folgende Codezeile als Schablone für die Verwendung von DataModule in Ihrem Code verwenden:

DataModule myDMod = DataModule.getDataModule();

dann können Sie auf das soeben erzeugte DataModule-Objekt in anderen Frames oder Applets zugreifen, so daß Sie seine Komponenten als Gruppe wiederverwenden können.

Database

Mehrere DataSet-Komponenten (wie etwa QueryDataSets und ProcedureDataSets) können dieselbe Database gemeinsam nutzen, indem sie ihre Database-Eigenschaften entsprechend setzen. Die Database-Eigenschaft Connection spezifiziert die URL, den Login-Namen, das Paßwort sowie optional einen JDBC-Treiber.

Daten bereitstellen

DataSet-Komponenten können Daten aus einer beliebigen JDBC-Datenquelle entgegennehmen. Die Database-Eigenschaft gibt an, für welche Connection die Abfrage erfolgen soll. Die Query-Eigenschaft ist ein String, der die SQL-Anweisung darstellt. Die ParameterRow-Eigenschaft ermöglicht, optionale Abfrageparameter anzugeben. Das executeOnOpen-Ereignis bewirkt, daß QueryDataSet die Abfrage beim ersten Öffnen ausführt, das sinnvoll ist, wenn echte Daten zur Entwurfszeit angezeigt werden sollen. Die Eigenschaft AsynchronousExecution bewirkt, daß die DataSet-Zeilen in einem eigenen Thread ermittelt werden, so daß ein Zugriff auf die Daten möglich ist, während QueryDataSet Zeilen aus der Connection lädt.

Die QueryDataSet-Komponente kann auf dreierlei Weise eingesetzt werden, um Daten zu laden:

Dynamisches Laden von Detail-Gruppen: Die MasterLinkDescriptor-Eigenschaft eines DataSet enthält eine FetchAsNeeded-Eigenschaft. Wenn diese Eigenschaft für ein QueryDataSet gesetztwird, wird die Detail-Abfrage ausgeführt, wenn zum ersten Mal eine neue Master-Zeile angetroffen wird.

Navigation und Bearbeiten von Daten

Nachdem Daten in ein DataSet geladen wurden, kann man sich darin bewegen. Diese Navigation kann relativ sein (nächster, vorhergehender, erster oder letzter Datensatz). Es kann entweder mit Hilfe der Methode goToRow() positioniert werden, oder es kann mit locate() oder lookup() nach einem Wert gesucht werden. Wenn das DataSet mit einem datenbezogenen Steuerelement der Benutzeroberfläche verbunden ist, verwaltet dieses Steuerelement die aktuelle Zeile im DataSet. Wenn das nicht gewünscht ist, verwenden Sie statt dessen ein DataSetView, das einen unabhängigen Cursor, eine Zeilensortierung und eine Filterung ermöglicht.

DataSet bietet außerdem Methoden zum Hinzufügen, Löschen und Aktualisieren von Zeilen im DataSet. Das Einfügen einer neuen Zeile in ein nicht sortiertes DataSet erfolgt am Ende dieses DataSets. Wenn das DataSet sortiert ist, wird die Zeile an der korrekten Position eingefügt. Außerdem gibt es die Methode getStatus(), die eine Bitmaske mit Statusinformationen zurückgibt. Die Biteinstellungen sind in der Klasse RowStatus definiert.

Sortieren und Filtern

Jedes DataSet kann eine eigene Spaltensortierung aufweisen, die in der Sort-Eigenschaft festgelegt wird. Der SortDescriptor spezifiziert auch Sortierungen ohne Berücksichtung der Groß-/Kleinschreibung und absteigende Reihenfolgen, die durch Indizes verwaltet werden. Indizes werden durch Aufruf von freeAllIndexes() (definiert in der Klasse StorageDataSet) freigegeben. Das Filtern wird durch Definition des RowFilter-Ereignisses der DataSet-Komponente bewerkstelligt. Wenn ein RowFilter-Ereignishandler parametrisiert ist, kann das DataSet gezwungen werden, den Filter durch Aufruf der Methode recalc() neu zu berechnen.

Master-Detail-Unterstützung

Diese Unterstützung wird aktiviert durch Setzen der MasterLink-Eigenschaft des Detail-DataSet, wodurch Spaltenwerte aus dem Master-DataSet mit dem Detail-DataSet verbunden werden. Beim Durchlaufen des Masters werden die Details mit übereinstimmenden Spaltenwerten angezeigt. Eine Master-Zeile kann nicht gelöscht werden, und eine Master-Link-Spalte kann nicht verändert werden, wenn ihr Detail-Zeilen zugeordnet sind. Ein Master-DataSet kann mehrere zugeordnete Detail-DataSet-Komponenten haben, und ein Detail-DataSet kann Master für ein anderes Detail-DataSet sein.

Es gibt zwei Ansätze für die Verwendung der Master-Detail-Funktionalität in QueryDataSet-Komponenten:

Auflösen eines Dataset

Die DataBroker-Architektur bietet eine umfangreiche Unterstützung zum Speichern von DataSet-Änderungen in einer JDBC-Datenquelle und zum Auflösen aller möglichen Konflikte. Die automatische Auflösung ruft die Methode saveChanges() (definiert in Database) für die DataSets (oder eine DataSet-Unterklasse) auf, so daß das Einfügen, Löschen oder Aktualisieren standardmäßig in einer einzigen Transaktion in der JDBC-Datenquelle erfolgt. Für eine angepaßte Auflösung wird die Resolver-Eigenschaft des DataSet verwendet. (Alle von StorageDataSet abgeleiteten DataSets besitzen diese Eigenschaft.) Sie können aber auch einen QueryResolver instantiieren, seine Eigenschaften und Ereignishandler setzen und dann die Resolver-Eigenschaft der DataSet-Komponente auf Ihre QueryResolver-Komponente setzen. Auf diese Weise können Sie steuern, wie Aktualisierungen vorgenommen werden und wie Konflikte aufgelöst werden.

Die Methode saveChanges() delegiert die Arbeit, Änderungen zu speichern, an eine Unterklasse, SQLResolutionManager. Hier folgt ein Codeabschnitt, der zeigt, wie die Methode saveChanges() arbeitet:

SQLResolutionManager resolutionManager = new SQLResolutionManager();
resolutionManager.setDatabase(this);
resolutionManager.setDoTransactions(true);
resolutionManager.savechanges(DataSets);

Datenbezogene Steuerelemente

In diesem Abschnitt werden die datenbezogenen Steuerelemente mit je einer kurzen Beschreibung vorgestellt. Um diese Komponenten mit den entsprechenden Datenzugriffs-Komponenten zu verbinden, klicken Sie auf den Dropdown-Pfeil in der DataSet-Eigenschaft und wählen einfach eine der DataSet-Unterklassen-Komponenten, die Ihnen in der Liste angezeigt werden.

GridControl

Wenn eine Tabellenspaltenüberschrift angeklickt wird, werden die Daten nach dieser Spalte in aufsteigender Reihenfolge sortiert. Wenn sie ein zweites Mal angeklickt wird, wird die Spalte in absteigender Reihenfolge sortiert. Die Tabelle benachrichtigt das DataSet, wenn sie die Spalten umsortiert, und diese Information wird von LocatorControl ausgewertet, welche Spalten gesucht werden sollen.

StatusBar

Wenn die DataSet-Eigenschaft eines StatusBar gesetzt wird, macht sie das StatusBar zu einem StatusListener des DataSet. Dann zeigt das StatusBar Informationen über die Navigation, die Berabeitung, den Fortschritt der Abfrageausführung sowie andere Statusmeldungen an.

NavigatorControl

Wenn die Dataset-Eigenschaft dieser Komponente gesetzt ist, können die Schaltflächen von NavigatorControl die Navigation steuern, Zeilen neu laden und speichern. Die Schaltflächen zum Neuladen und Speichern werden nur für QueryDataSet- und ProduceDataSet-Komponenten aktiviert.

LocatorControl

Die Komponente LocatorControl hat DataSet- und ColumnName-Eigenschaften, um einen interaktiven Suchmechanismus an eine Spalte zu binden. Wenn die Spalte nicht angegeben ist, wird die erste Spalte im DataSet geladen. Wenn sie mit einem GridControl verbunden ist, wird die zuletzt betrachtete Spalte geladen. Für Spalten vom Typ String wird eine inkrementelle Suche unterstützt, wobei die Groß-/Kleinschreibung nicht berücksichtigt wird, wenn nur Kleinbuchstaben eingegeben werden.

ChoiceControl

Durch Setzen der DataSet-Eigenschaft dieser Komponente kann die PickListDescriptor-Eigenschaft von ColumnComponent verwendet werden, um die Auswahlliste zu füllen.

Zusammenfassung

Heute haben Sie JDBC als Low-Level-Löstung für die Verbindung zu einer SQL-Datenbank kennengelernt, und Sie haben gesehen, daß Performance und Sicherheit zum Thema werden können, wenn Sie Ihre Java-Programme mit einem SQL-Host verbinden. Außerdem haben Sie das JDBC-API kennengelernt, sowie ein Beispiel, wie ein Java-Programm eine Verbindung zu einer SQL-Datenbank einrichten, diese Abfragen und die Ergebnisse zurückgeben könnte.

Sie haben die Datenzugriffs-Komponenten von JBuilder als High-Level-Lösung für die Verbindung mit SQL-Datenbanken und die Verwendung des JDBC-API kennengelernt. Die DataBroker-Architektur wurde vorgestellt. Außerdem wurden die datenbezogenen Komponenten kurz gezeigt.

Dies war jedoch nur eine kurze Einführung in die Möglichkeiten, die JDBC und die Datenzugriffskomponenten von JBuilder bieten.

F&A

F Kann JDBC neue Sicherheitsrisiken aufwerfen?

A JDBC wurde sorgfältig drauf ausgelegt, daß es demselben Sicherheitsmodell wie Java unterliegt. Ein neues Sicherheitsrisiko, das ein Problem darstellen könnte, kommt jedoch mit den BLOBs (Binary Large Objects). Der BLOB, in SQL auch als Datentyp LONG RAW realisiert, wird normalerweise genutzt, um binäre Daten zu speichern, unter anderem Grafik und Sound. Das könnte zu einer Sicherheitslücke zum Einschleusen von Viren oder fremdem Code in das Client-System führen.

F Mit Hilfe von ODBC kann ich eine SQL-Anweisung asynchron ausführen. Bietet Java etwas ähnliches?

A Java bietet noch etwas viel besseres: Multithreading. Der DriverManager kann mehrere Verbindungen zur Datenbank gleichzeitig einrichten, und jede dieser Verbindungen kann mehrere Anweisungen ausführen. So wie Animationen können Sie auch SQL-Anweisungen in ihre eigenen Threads einbetten.

Workshop

Der Workshop bietet zwei Möglichkeiten, zu überprüfen, was Sie in diesem Kapitel gelernt haben. Der Quiz-Teil stellt Ihnen Fragen, die Ihnen helfen sollen, Ihr Verständnis für den vorgestellten Stoff zu vertiefen. Die Antworten auf die Fragen finden Sie in Anhang A. Der Übungen-Teil ermöglicht Ihnen, Erfahrungen in der Anwendung der Dinge zu sammeln, die Sie hier kennengelernt haben. Versuchen Sie, diese Dinge durchzuarbeiten, bevor Sie mit der nächsten Lektion weitermachen.

Quiz

Übung

Experimentieren Sie anhand von Listing 14.1 mit einer eigenen Tabelle und greifen Sie über eine SQL-Abfrage auf verschiedene Datenzeilen zu und geben Sie diese aus.


© 1997 SAMS
Ein Imprint des Markt&Technik Buch- und Software- Verlag GmbH
Elektronische Fassung des Titels: JBuilder in 14 Tagen, ISBN: 3-87791-895-6

Previous Page Page Top TOC Index Next Page See Page