Weitere aktuelle Java-Titel finden Sie bei dpunkt.
 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index


18.4.4

Datenquellen



JDBC-Datenquellen[1.4] sind in ihrer Anwendung flexibler als das Treibermanager-API und könnten die Klasse DriverManager als Standardmechanismus für das Erzeugen von Datenbankverbindungen ablösen. Datenquellen sind seit der J2SDK 1.4 in den Standardklassen enthalten.

Datenquellen verbergen den Mechanismus, über den neue Datenbankverbindungen aufgebaut werden. Nach der einmaligen Initialisierung der Datenquelle kann man über eine Datenquelle beliebig viele Verbindungen zum selben Datenbanksystem aufbauen, ohne die erneute Angabe von Verbindungsparametern. Datenquellen werden z. B. häufig an eine JNDI-Verzeichnishierarchie gebunden und später von Anwendungen über einen logischen Namen abgerufen (siehe Kapitel 17). Dadurch braucht die Anwendung keine Verbindungsinformationen zur Datenbank, sondern lediglich den logischen Namen der Datenquelle im JNDI-Verzeichnis. Oracle8i verwendet z. B. dieses Prinzip:

Für JDBC-Datenquellen gibt es folgende Einsatzgebiete:

Abbildung 18.8: Übersicht über die verschiedenen JDBC-Datenquellen
Abbildung 18.8

Eine Klasse, die eine JDBC-Datenquelle darstellt, implementiert im einfachsten Fall das Java-Interface DataSource. Dieses Interface definiert Methoden, über die man Verbindungsinformationen setzen und danach Verbindungen in Form von Connection-Exemplaren abrufen kann. Für die Unterstützung wiederverwendbarer Verbindungen und Verbindungen für verteilte Transaktionen wurden die Java-Interfaces PooledConnectionDataSource bzw. XAConnectionDataSource definiert. Die beiden zuletzt genannten werden in der Praxis jedoch weniger häufig verwendet und sind lediglich als Lowlevel-API anzusehen, die für die Implementierung höherwertiger Dienste benutzt werden. Exemplare einer PooledConnectionDataSource kann man z. B. in einem Connection Pool für die Erzeugung von Verbindungen einsetzen (siehe Abschnitt 18.10.3). Von XADataSource wird z. B. in Implementierungen des JTA (Java-Transaction-API) Gebrauch gemacht.

Die einzelnen Typen von JDBC-Datenquellen werden in Abbildung 18.8 gegenübergestellt.

Prinzipiell gibt es zwei Initialisierungs-Alternativen:

Lokale Initialisierung in der Anwendung

Für die lokale Initialisierung einer Datenquelle muss man folgende Schritte durchführen: Die Umsetzung der einzelnen Schritte wird im Folgenden am Beispiel einer Datenquelle für einfache Datenbankverbindungen gezeigt.
  // Import-Anweisungen zur Nutzung der Datenquelle
  import java.sql.*;
  import oracle.jdbc.pool.OracleDataSource;
  import javax.sql.DataSource;
  ...
  // Laden des JDBC-Treibers
  Class.forName("oracle.jdbc.driver.OracleDriver");
  // Erzeugen einer neuen Datenquelle
  DataSource ds = new OracleDataSource();
  // Setzen von Verbindungsparametern
  ((OracleDataSource)ds).setUser("shop");
  ((OracleDataSource)ds).setPassword("shop");
  ((OracleDataSource)ds).setDriverType("thin");
  ((OracleDataSource)ds).setPortNumber(1521);
  ((OracleDataSource)ds).setServerName("localhost");
  ((OracleDataSource)ds).setDatabaseName("orcl");
  // Aufbauen einer neuen Verbindung
  Connection con = ds.getConnection();
  // Hier Ausführen von SQL-Anweisungen
  ...
  // Schließen der Verbindung
  con.close();
  ...
Im Beispiel wird die neue Datenquelle in einer Variable vom Typ DataSource gespeichert. Da die Methoden zum Setzen der Verbindungsinformation Oracle-spezifisch sind, muss beim Aufruf ein Cast in OracleDataSource durchgeführt werden. Im Beispiel werden die Parameter jeweils einzeln gesetzt. Prinzipiell ist es auch möglich, alle Verbindungsparameter gemeinsam über die Methode setURL() zu setzen:
  String url = "jdbc:oracle:thin:shop/shop@localhost:1521:orcl";
  ((OracleDataSource)ds).setURL(url);
Auf diese Weise kann man sich einige Zeilen Quellcode sparen.

In der Client-Anwendung initialisierte JDBC-Datenquellen können im Programmcode auch an das serverseitige JNDI-Verzeichnis gebunden werden, jedoch nur, wenn die Bindung serverintern ausgeführt wird. Hierzu muss man aus dem JNDI-Verzeichnis über eine Lookup-Operation den entsprechenden Kontext aufrufen und über die Methode bind() die neu erzeugte Datenquelle unter einem Namen an den Kontext binden:
  DataSource ds;
  // Datenquelle anlegen und intialisieren
  ...
  InitialContext ic = new InitialContext();
  // Server-seitiges Lookup des Kontextes
  Context ctx = (Context)ic.lookup("/jdbc");
  // Binden der Datenquelle in den Kontext
  ctx.bind("shopds", ds);
  ...

Protokollierung

Sowohl Datenquellen als auch das Treibermanager-API verfügen über eine integrierte Protokollfunktionalität. Protokolliert werden treiberinterne Aktionen, die für die Fehlersuche in der eigenen Anwendung hilfreich sein könnten. Die Protokollierung ist per Voreinstellung deaktiviert und muss explizit über die Methode setLogWriter() aktiviert werden. Folgendes Beispiel zeigt, wie das Protokoll des JDBC-Treibers über eine JDBC-Datenquelle in die Datei test.log geschrieben wird:
  FileWriter logfile = new FileWriter("test.log");
  DataSource ds;
  // Hier Initialisierung der Datenquelle
  ...
  // Setzen des Protokoll-Streams
  ds.setLogWriter(new PrintWriter(logfile));
  ...
Die Aktivierung der Protokollierung über das Treibermanager-API funktioniert entsprechend. Im folgenden Beispiel wird das Treiberprotokoll des Treibermanagers auf der Standard-Ausgabe ausgegeben:
  PrintWriter logger;
  logger = new PrintWriter(new OutputStreamWriter(System.out));
  DriverManager.setLogWriter(logger);
  // Jetzt Aufbau der Verbindung und 
Die Aktivierung der Protokollierung muss nicht unbedingt zu Beginn erfolgen. Sie kann an beliebiger Stelle initiiert werden und wirkt sich auf alle folgenden Operationen aus.

Ein Beispiel für ein Protkoll des Oracle-Treibers ist in Abbildung 18.9 dargestellt.

Abbildung 18.9: Beispiel eines JDBC Treiber-Protokolls (Oracle)
Abbildung 18.9

Es wurde vom folgenden Code erzeugt:

  DataSource ds;
  ...
  Connection con = ds.getConnection();
  ds.setLogWriter(new PrintWriter(new OutputStreamWriter(System.out)));
  Statement stmt = con.createStatement();
  String sql = "INSERT INTO autoren values('Singer', 'Reiner', 3, 1, 11)";
  stmt.executeUpdate(sql);
  prep.close();
  con.close();
  ...
Die Protokollierung kann zu jeder Zeit wieder deaktiviert werden, indem man setLogWriter() mit dem Wert null als Parameter aufruft:
  ds.setLogWriter(null);


 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index

Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.