Java und JDBCTM Datenbankanwendungen mit Java und JDBC Martin Beck 96I [email protected] Inhalt 1. 2. 3. 4. 5. 6. 7. 8. 9. Ziel von Datenbanken im Internet und Intranet Java und JDBC kurz und bündig ODBC und Java JDBC JDBC-Treibertypen OpenLink-Middleware Struktur einer JDBC-Anwendung Servlets und JDBC Beispiele ... Martin Beck 96I [email protected] 1. Ziel von Datenbanken im Internet und Intranet Beispiele: 1. Internes Telefonverzeichnis eines Unternehmens Verfügbarmachen d. Verzeichnisses in Online-Form für alle Mitarbeiter 2. Warenwirtschaftssystem arbeitet als Datenbankanwendung mit einem sehr großen Datenbestand Datenauswertungen und Eingabemöglichkeiten an allen Arbeitsplätzen ... Ziel: "Information at your fingertips" - sämtliche Informationen laufen am __Arbeitsplatz des Mitarbeiters zusammen. Bill Gates, der den obigen Begiff prägte, stellt sich überall Windows-Systeme vor: auf jedem Arbeitsplatz als Desktop-System und im "BackOffice" als Server. Dank WWW und Java ist diese Ausschließlichkeit nicht zwingend. Martin Beck 96I [email protected] 2. Java und JDBC kurz und bündig Ein wichtiger Grund für die in so kurzer Zeit derart weite Verbreitung der von Sun Microsystems entwickelten Programmiersprache Java liegt in der Plattformunabhängigkeit der Sprache. Einzige Voraussetzung für Java ist eine Java-Laufzeitumgebung mit ihrer zentralen Komponente, der Java Virtual Machine (JVM). Die Übersetzung eines Java-Quellprogramms erzeugt einen sog. Bytecode. Was bringt JDBC? Mit JDBC hat Sun Microsystems einen Standard definiert, um aus Java-Programmen heraus auf relationale Datenbanksysteme zugreifen zu können. JDBC steht für Java Database Connectivity. JDBC stellt ein API (Application Programming Interface) zur Verfügung. Martin Beck 96I [email protected] 2. Java und JDBC kurz und bündig Zwei Besonderheiten zeichnen JDBC aus: Der Datenbankzugriff erfolgt unabhängig vom verwendeten DBMS. Der Datenbank-Client braucht (und sollte) nicht mit einem bestimmten DBMS "im Hinterkopf" entwickelt werden. Alle DBMS-spezifischen Details übernimmt ein JDBC-Treiber. Er ist ebenfalls in Java geschrieben und wird von den Datenbankherstellern oder von Dritten angeboten. Martin Beck 96I [email protected] 3. ODBC und Java Das von Microsoft spezifizierte ODBC (Open Database Connectivity) bietet Datenbank-Clients ein einheitliches Verfahren zum Zugriff auf Datenbanksysteme verschiedener Hersteller. Frage: Warum nutzt Java nicht einfach ODBC um auf Datenbanken zuzugreifen? Antwort: Dies ist im allgemeinen nicht möglich oder zumindest nicht wünschenswert, weil dadurch die Plattformunabhängigkeit der JavaAnwendung auf der Strecke bleibt. Grund: ODBC ist ein API für C und C++. Nur C- und C++-Programme sind in der Lage, die ODBC-Schnittstellen zu nutzen und die im Standard definierten Funktionen aufzurufen. Martin Beck 96I [email protected] 4. JDBC Vermeidung der genannten Einschränkungen Funktion ähnlich ODBC, lediglich Datenstrukturen sind anders keine Pointer und Handles, sondern Klassen, Objekte und Methoden JDBC-Anwendung öffnet eine Datenbank eines beliebigen DBMS Voraussetzung: JDBC-Treiber für dieses DBMS Ein JDBC-Treiber ist in Java geschrieben und wird vom Programm zur Laufzeit hinzugeladen Portabilität ist gegeben, da Implementierung in Java JDBC spezifiziert das API und bietet mit der Komponente JDBC-Treibermanager einen Rahmen für JDBC-Treiber Konkrete JDBC-Treiber für konkrete Datenbanksysteme enthält JDBC nicht ! solche Treiber stammen von den Datenbankherstellern deshalb braucht man nicht damit rechnen, daß man mit einem Treiber des Herstellers A auf das DBMS des Herstellers B zugreifen kann. Martin Beck 96I [email protected] 4. JDBC Strategische Vorteile von JDBC: Datenbank-Client ist unabhängig von einer best. Zielplattform. Datenbanklösung ist unabhängig von der Serverplattform. Anwendung ist durch JDBC unabhängig vom DBMS, da JDBC-Treiber für praktisch alle DBMS verfügbar sind. Das Unternehmen, das eine JDBC-Lösung einsetzt, hat damit alle Daten überall im Intranet verfügbar, ganz gleich, mit welchem Rechnertyp der Benutzer arbeitet und ganz gleich, in welchem Datenbanksystem und auf welcher Maschine die Daten vorliegen. JDBC macht es auch möglich, Daten aus ganz unterschiedlichen Systemen innerhalb der Anwendung zusammenzuführen. Martin Beck 96I [email protected] 5. JDBC-Treibertypen Ein JDBC-Treiber stellt für den Client eine einheitliche Schnittstelle zur Verfügung. Jeder Treiber ist auf ein bestimmtes DBMS bzw. auf ein bestimmtes Zugriffs- ----verfahren nach dem Zwei- oder Dreischichtenmodell zugeschnitten. Das Zweischichtenmodell realisiert einen einfachen Client-/Server-Datenbank-------zugang. Das Dreischichten- oder Mehrschichtenmodell führt zwischen Client und Server ----eine weitere Schicht ein, die den Client vom DBMS unabhängig macht und so die --Probleme des Zweischichtenmodells vermeidet. Die Zwischenschicht wird -----------Middleware genannt. --Der Client wendet sich zum Öffnen der DB nicht direkt an das DBMS, sondern an --die Middleware. Die gewünschte DB spezifiziert der Client bei JDBC mit einem ------JDBC-URL. Die Middleware analysiert diesen und lädt den benötigten DBMS---------Treiber, der seinerseits die Verbindung zur DB herstellt. Vier Typen von JDBC-Treibern sind zu unterscheiden (siehe nächste Folie). Martin Beck 96I [email protected] 5. JDBC-Treibertypen 1. Typ 1 ist eine JDBC-ODBC-Bridge - eine einfache Lösung für beliebige ODBC-Datenbanken Vorteil: Kann bereits zu einem frühen Zeitpunkt auf sämtliche ODBC-Datenbanken zugreifen Nachteil: Nicht ausschließlich Bytecode, daher nicht portabel und plattformunabhängig 2. Typ 2 ist eine Art Zwischenlösung z.B. für DB-Hersteller, der den bereits bestehenden Treiber (z.B. C) seines DBMS hernimmt und eine JDBC-Schicht oben aufsetzt Nachteile: siehe 1. 3. Typ 3 ist ein hundertprozentiger Java-Treiber, mit der größtmöglichen Flexibilität und fügt sich nahtlos in das Dreischichtenmodell ein. 4. Typ 4 ist ebenfalls ein reiner Java-Treiber, entspricht aber dem Zweischichtenmodell Java-Anwendung JDBC-Treibermanager JDBC-ODBCBridge-Treiber Treiber für DBMS B (Java) ODBC-Treiber Treiber für DBMS B (C) Standard JDBC-Treiber Treiber für DBMS D (Java) Middleware DBMS A DBMS B DBMS C DBMS D Typ 1 Typ 2 Typ 3 Typ 4 Abb.: JDBC-Treibertypen Martin Beck 96I [email protected] 6. OpenLink-Middleware Die OpenLink Software Ltd. Bietet eine leistungsfähige und hochperformante Middleware, die eine universelle Infrastruktur für Datenbankzugriffe bereitstellt. Java-Anwendung C++ / C-Anwendung OpenLink-JDBC-Treiber OpenLink-ODBC-Treiber OpenLink Request Broker InformixAgent Informix OracleAgent ODBCAgent Oracle ODBC-DB Abb.: Die OpenLink-Middleware Martin Beck 96I [email protected] 7. Struktur einer JDBC-Anwendung Ein in Java geschriebener Datenbank-Client besitzt einen bestimmten Grundaufbau, um seine Aufgaben mit Hilfe von JDBC zu erledigen. Folgende Schritte sollte jedes JDBC-Programm ausführen: 1. 2. 3. 4. 5. Laden eines JDBC-Treibers Öffnen einer Datenbank Senden von SQL-Anweisungen an die Datenbank Auslesen und Bearbeiten der Ergebnisse Schliessen der Datenbank Martin Beck 96I [email protected] 7. Struktur einer JDBC-Anwendung Zu 1. Der erste Schritt auf dem Weg zur DB ist das Laden eines JDBC-Treibers h Class.forName("openlink.jdbc.Driver"); h Wird der Treiber nicht gefunden, wird die Ausnahme java.lang.ClassNotFoundException erzeugt. Um diesen abzufangen benötigt man also ein entsprechendes try{} catch(). Zu 2. Nachdem der Treiber geladen ist und beim Driver-Manager registriert ist, gilt es eine Verbindung zur Datenbank aufzubauen. Dazu benötigt man die Methode getConnection() der DriverManager-Klasse: String url = "jdbc:openlink://localhost/plz/DSN=dsn_oracle"; Connection con = DriverManager.getConnection(url, argv[0], argv[1]); Als Parameter muß der Methode üblicherweise ein Nutzername und ein Passwort übergeben werden, die den Zugriff auf die Datenbank legitimieren. Ausserdem muß ein String (JDBC-URL) übergeben werden. Der Rückgabewert ist ein Objekt der Schnittstelle con - darüber werden die Datenbank-Anfragen und deren Ergebnisse abgewickelt. (DSN = Data Source Name --> Datenquelle mit Zugriffsparametern) Martin Beck 96I [email protected] 7. Struktur einer JDBC-Anwendung Zu 3. Über die nunmehr geöffnete DB-Verbindung sendet der Client SQL-Anweisungen an das DBMS. Dazu erzeugt er ein Statement-Objekt, schreibt den SQL-Befehl hinein und übermittelt ihn mit Hilfe des JDBC-Treibers und der Statement-Methode executeQuery() an das DBMS. h Statement stmt = con.createStatement(); String query = "SELECT ... FROM ... WHERE ... = ... AND ... = ... "; ResultSet rs = stmt.executeQuery(query); h Zu 4. Das Ergebnis einer SELECT-Anweisung ist eine Tabelle. Der JDBC-Treiber stellt sie als Instanz der Klasse ResultSet zur Verfügung. Diese Klasse besitzt Methoden zum Durchlaufen der Tabelle und zum Zugriff auf die Ergebnisse. Die Anwendung bearbeitet das ResultSet zeilenweise von vorn nach hinten. Um dynamisch Spaltennamen und -anzahl zu ermitteln sind nachfolgende Zeilen zu schreiben: ResultSetMetaData rsmd = rs.getMetaData(); int columns = rsmd.getColumnCount(); ... Martin Beck 96I [email protected] 7. Struktur einer JDBC-Anwendung Zu 5. Es ist ein guter Programmierstil, die zuvor geöffneten Objekte zu schließen. Die Ressourcenfreigabe ist es, die ein vorzeitiges, explizites Schließen von JDBC-Objekten sinnvoll machen kann. Wer mit großen Datenmengen hantiert, sollte ResultSet und Statement möglichst frühzeitig schließen, damit die nicht mehr benötigten Objekte und Daten nicht unnötig Speicherplatz blockieren. Es ist natürlich nicht sinnvoll, Connections andauernd zu schließen und wieder zu öffnen, denn der Aufbau der Datenbankverbindung ist recht zeitintensiv. rs.close(); stmt.close(); con.close(); Martin Beck 96I [email protected] 8. Servlets und JDBC Um per Java auf Datenbanken zuzugreifen, kann man sich mehrerer Möglichkeiten bedienen. Zum einen über ein Java-Applet, welches im Browser auf der Client-Seite abläuft. Weiterhin ist auch eine Java-Applikation denkbar, welche ebenfalls clientseitig abläuft. Diese beiden Varianten werden als "grafischer JDBC-Client" bezeichnet. Dann gibt es noch "verteilte Anwendungen", wo allein die grafische Benutzeroberfläche (Java-Oberfläche) beim Client bleibt. Die Java-Anwendung läuft auf einem Anwendungsserver. Client und Server kommunizieren über RMI (Remote Method Invocation). Als Drittes gibt es noch die Java-Servlets, die ebenfalls auf der Serverseite ablaufen und lediglich HTML an den Client zurückliefern. Hier ist keine JVM auf der Client-Seite notwendig. Allerdings muß der Webserver eine Servletunterstützung haben. Martin Beck 96I [email protected] 8. Servlets und JDBC JavaAnwendung HTMLOberfläche JavaOberfläche JDBC Netz Netz Netz HTTP RMI AnwendungsServer WWW-Server JDBC Java-Servlet JDBC DBMS A Abb.: Grafischer JDBC-Client Martin Beck 96I DBMS A Abb.: Verteilte Anwendung DBMS A Abb.: Web-Datenbank mit HTML-Oberfläche [email protected] 8. Servlets und JDBC Ein Servlet besitzt zwei Vorteile: 1. Es ist in Java geschrieben und daher unabhängig von der Server-Plattform. Es kann per JDBC auf Datenbanken zugreifen. 2. Das Servlet besitzt eine standardisierte Schnittstelle und ist damit unabhängig vom Web-Server Der Server muß das Servlet-API unterstützen. (z.B. Jeeves von Sun, Jigsaw von W3C oder Apache mit Aufsatz AnyJ) Warum Servlets und nicht CGI? Zum einen wegen der Plattformunabhängigkeit und zum anderen wegen der besseren Performance. Der Nachteil von CGI-Skripts besteht in ihrer Ineffizienz. Der WWW-Server muß für jeden einzelnen CGI-Aufruf einen neuen Prozeß starten. Bei geringer Last funktioniert das recht gut, bei hohen Zugriffszahlen geht das System jedoch in die Knie und es kommt zu inakzeptablen Antwortzeiten oder zu Totalausfall. Martin Beck 96I [email protected] 9. Beispiele import java.sql.*; /* Ein erstes JDBC-Beispiel */ class Simple { public static void main(String argv[]) throws java.lang.ClassNotFoundException, java.sql.SQLException { // JDBC-Treiber laden: Class.forName("openlink.jdbc.Driver"); //eigentlich mit try Exceptions abfangen, hier nur //nach oben durchgereicht und beenden // Datenbankverbindung aufbauen: String url = "jdbc:openlink://localhost/DSN=dsn_postgres/DATABASE=plz"; Connection con = DriverManager.getConnection(url, argv[0], argv[1]); // Statement erzeugen: Statement stmt = con.createStatement(); // Abfrage ausführen: String query = "SELECT ge_name, ge_plz_ge, ort_oname" + " FROM gross_da, ort_da" + " WHERE ge_alort_ge = ort_alort" + " AND ort_oname = 'Dortmund'" + " ORDER BY ge_name;"; Martin Beck 96I [email protected] 9. Beispiele ResultSet rs = stmt.executeQuery(query); // Ergebnisse als HTML-Tabelle ausgeben: System.out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN//\">"); System.out.println("<TITLE>SQL-Abfrage mit JDBC</TITLE>"); System.out.println("<H1>SQL-Abfrage mit JDBC</H1>"); System.out.println("<H2>Abfrage:</H2>"); System.out.println("<P>" + query + "</P>"); System.out.println("<H2>Ergebnistabelle:</H2>"); System.out.println("<TABLE BORDER='1'>"); ResultSetMetaData rsmd = rs.getMetaData(); int columns = rsmd.getColumnCount(); //Spaltennamen aus Metadaten ermitteln // Erste Tabellenzeile enthält die Spaltennamen: System.out.println("<TR>"); for (int i = 1; i <= columns; i++) System.out.println(" <TH>" + rsmd.getColumnName(i) + "</TH>"); System.out.println("</TR>"); Martin Beck 96I [email protected] 9. Beispiele // Ergebniszeilen ausgeben: while (rs.next()) { System.out.println("<TR>"); // neue Tabellenzeile for (int i = 1; i <= columns; i++) System.out.print(" <TD>" + rs.getObject(i) + "</TD>"); System.out.println("</TR>"); // Tabellenzeile schließen } System.out.println("</TABLE>"); // Tabelle schließen rs.close(); // ResultSet schließen // Statement-Objekt schließen: stmt.close(); // Datenbankverbindung schließen: con.close(); } } Martin Beck 96I [email protected] 9. Beispiele import /* Ein import import java.io.*; erstes Servlet-Beispiel (im JSDK von Sun enthalten)*/ javax.servlet.*; javax.servlet.http.*; public class HelloWorldServlet extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); out.println("<HTML>"); out.println("<TITLE>Hello World</TITLE>"); out.println("<BODY>"); out.println("<H1>Hello World</H1>"); out.println("</BODY></HTML>"); } public String getServletInfo() { return "Create a Page that says " + "<I>Hello World</I> and send it back"; } } Martin Beck 96I [email protected] Literaturangaben 1 http://java.sun.com 2 http://java.seite.net 3 http://www.openlink.de 4 Rainer Klute: Einführung in JDBC Addison Wesley 5 Roßbach,Schreiber: Java Server und Servlets Martin Beck 96I Sun Microsystems OpenLink Middleware Addison Wesley [email protected]