JDBC Java DataBase Connectivity
JDBC-Schichten JDBC besteht aus 2 Teilen, 1. aus Datenbanktreibern, die den Anschluß von Java-Anwendungen an Datenbanksysteme wie Sybase, DB/2, Oracle, MS ACCESS oder Mini SQL ermöglichen und 2. aus dem Paket java.sql, bestehend aus einem Manager für diese Treiber sowie Interfaces als Schnittstellen zu den Treibern. JDBC Treiber- Manager Java Applikation JDBC Treiber 1 JDBC Treiber 2... JDBC Treiber n Herstellerspezifisches Datenbankzugriffsprotokoll Datenbanken 2
JDBC-Konformität Treiber können sich dann als JDBC COMPLIANT, d.h. JDBC-konform bezeichnen, wenn sie SUNs Konformitätstest bestehen und damit u.a. mindestens dem sog. ANSI/ISO SQL/92 Entry Level genügen. // Programm JdbcKonform public class JdbcKonform { public static void main(string[] args) throws Exception { System.out.println("ODBC " + (new sun.jdbc.odbc.jdbcodbcdriver()).jdbccompliant()); System.out.println("MiniSQL " + (new com.imaginary.sql.msql.msqldriver()).jdbccompliant()); // Programm AnsiStufe import java.sql.*; public class AnsiStufe { public static void main(string[] args) throws Exception { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection("jdbc:odbc:Kurse", "gast", ""); DatabaseMetaData meta = c.getmetadata(); System.out.println(meta.getDatabaseProductName() + " " + meta.getdatabaseproductversion() ); System.out.println("Entry Level " + meta.supportsansi92entrylevelsql()); System.out.println("Intermediate " + meta.supportsansi92intermediatesql()); System.out.println("Full Level " + meta.supportsansi92fullsql()); Antwort beispielsweise einer MS Access-Datenbank: ACCESS 3.5 Jet Entry Level true Intermediate false Full Level false 3
JDBC-Umfeld Java SQL JDBC Client/Server 4
JDBC-Grundlagen (1) Die fünf Schritte der JDBC-Programmierung : 1. Einen Treiber registrieren. 2. Über diesen Treiber Verbindung mit der Datenbank aufnahmen. 3. Ein SQL-Anweisungsobjekt erzeugen oder vorbereiten. 4. Eine SQL-Anweisung ausführen. 5. Das Resultat der Anweisung, den Resultset, verarbeiten. 5
JDBC-Grundlagen (2) 1. Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Mit Class.forName() wird die Klasse JdbcOdbcDriver aus dem Paket sun.jdbc.odbc geladen, instanziiert und die Instanz im Treibermanager registriert. Jedes JDBC-Programm hat genau ein Treiberregister. 2. Connection c =DriverManager.getConnection ("jdbc:odbc:kurse","gast",""); Die Verbindung mit einer Datenbank wird über einen String hergestellt, der Ähnlichkeit mit der Syntax eines URL (mailto:x@y.z, http://www.jugs.org etc.) hat und deshalb auch JDBC-URL heißt: jdbc:odbc:kurse. 3. Statement s = c.createstatement(); Es wird ein Statement-Objekt zur Anwendung an der Datenbank Kurse erzeugt. 4. ResultSet r = s.executequery ("SELECT * FROM Personen WHERE nachname LIKE 'K%'"); Sodann wird mit Hilfe dieses Statement-Objektes eine SELECT-SQL-Anweisung auf die Datenbank angewendet. Die Ausführung der SQL-Anweisung erfolgt mittels der Methode executequery() im Statement-Objekt s. Dabei werden in der Tabelle Personen alle Zeilen ausgewählt, in denen die Werte der Spalte nachname mit einem K beginnen. Die executequery()-methode gibt eine entsprechende Tabelle als sog. ResultSet zurück. 5. while(r.next()) { System.out.println(r.getString("vorname") +", "+ r.getstring("nachname")); In der while-schleife werden mit der Cursor -Methode next() nacheinander die Tabellenzeilen der Ergebnistabelle (Resultset) eingelesen und aus den Zeilen jeweils vorname und nachname extrahiert (getstring("spaltenname")) und ausgedruckt. 3 Regeln Zu jedem Statement-Objekt gibt es höchstens ein gültiges ResultSet-Objekt. Auf ein Datenelement in einer Zeile eines ResultSet kann höchstens einmal zugegriffen werden (z.b. mit getstring(("vorname")). Es geht nur vorwärts durch die Zeilen einer Tabelle (next()). 6
JDBC-Grundlagen (3) Registrieren java.sql.drivermanager Instanziieren java.sql.xxxdriver Verbinden java.sql.drivermanager Verbinden java.sql.driver CallableStatement Statement PreparedStatement java.sql.connection java.sql.connection java.sql.connection Ausführen java.sql.callablestatement Ausführen java.sql.statement Ausführen java.sql.preparedstatement Auswerten java.sql.resultset 7
Ein Musterprogramm // Programm FuenfSchritte import java.sql.*; public class FuenfSchritte { public static void main(string[] args) throws Exception { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection c = DriverManager.getConnection("jdbc:odbc:Kurse","",""); Statement s = c.createstatement(); ResultSet r = s.executequery ("SELECT * FROM Personen"); while(r.next()) { System.out.println(r.getString("vorname") + ", " + r.getstring("nachname")); 8
Framework Timestamp Driver java.sql Time Connection javautil.date Date Statement java.lang.object DriverManager PreparedStatement DriverPropertyInfo ResultSet CallableStatement Interface Klasse Types DatabaseMetaData ResultSetMetaData Treiber sun.jdbc.odbc java.sql JdbcOdbcDriver Driver JdbcOdbcConnection Connection JdbcOdbcStatement Statement JdbcOdbcPreparedStatement PreparedStatement JdbcOdbcCallableStatement CallableStatement JdbcOdbcResultSet ResultSet JdbcOdbcDatabaseMetaData DatabaseMetaData JdbcOdbcResultSetMetaData ResultSetMetaData Klasse implements Interface 9
Treiber Interface package java.sql; // alle Methoden sind implizit abstract und public! public interface DatabaseMetaData { int getmaxcolumnnamelength() throws SQLException; boolean supportstransactions() throws SQLException; Implementierung package sun.jdbc.odbc; import java.sql.*; public class JdbcOdbcDatabaseMetaData implements DatabaseMetaData {... public int getmaxcolumnnamelength() throws SQLException { return 64; public boolean supportstransactions() throws SQLException { return true; 10
Treiber (2) JDBC-Treiber können entweder explizit oder mittels des Treibermanager DriverManager instanziiert werden. Instanziieren mittels Treibermanager (Treiber für den DB-Server Mini SQL) Treiber laden Class.forName("com.imaginary.sql.msql.MsqlDriver"); Mit dem Laden der Klasse MsqlDriver wird deren statischer Konstruktor aufgerufen: static { try { new MsqlDriver(); catch( SQLException e ) { e.printstacktrace(); Im statischen Konstruktor wird ein Treiberobjekt der Klasse MsqlDriver erzeugt; dabei wird deren Konstruktor MsqlDriver() aufgerufen. Der Treiber registriert sich selbst durch Aufruf der Klassenmethode registerdriver(this) in der Klasse DriverManager. public MsqlDriver() throws SQLException { super(); DriverManager.registerDriver(this); Das Register ist ein statisch definierter Container vom Typ Vector in der Klasse DriverManager, also nur einmal in einem Java-Programm vorhanden. 11
Treiber (3) JDBC-Treiber können entweder explizit oder mittels des Treibermanager DriverManager instanziiert werden. Explizite Instanziierung unter Umgehung des Treibermanagers Die Treiberobjekte werden direkt erzeugt und im Anwendungsprogramm verwaltet. Für die obigen Beispiele ergeben sich als entsprechende Befehlszeilen: Sun ODBC-Treiber Driver dodbc = (Driver) new sun.jdbc.odbc.jdbcodbcdriver(); Mini SQL-Treiber Driver dmsql = (Driver) new com.imaginary.sql.msql.msqldriver(); Man beachte, daß die Typumwandlung vom Treibertyp MsqlDriver bzw. JdbcOdbcDriver auf den allen JDBC-Treibern gemeinsamen Supertyp Driver unabdingbar ist. 12
Treiber (4) Verbindungsaufbau mit Datenbanken Mit Treibermanager Um Verbindung mit Datenbanken aufzunehmen, wird die statische Methode getconnection() in der Klasse DriverManager aufgerufen. Als Parameter ist bei allen Methodenvarianten die Zieldatenbank in URL-Schreibweise anzugeben. Beispiele: oder String url = "jdbc:odbc:kurse"; Connection c = DriverManager.getConnection(url, "gast", ""); String url = "jdbc:msql://p1.inf.uni-hohenheim.de:1112/kurse"; Connection c = DriverManager.getConnection(url, "gast", ""); Nach Aufruf der Klassenmethode getconnection() geht der Treibermanager die registrierten Treiber durch und probiert bei jedem aus, ob eine Verbindung mit dem DBS herstellbar ist. Das geschieht durch Aufruf der Methode connect() in dem jeweiligen registrierten Treiberobjekt. Kommt eine Verbindung zustande, so gibt die Methode ein Connection-Objekt zurück. Kommt über keinen der registrierten Treiber eine Verbindung zustande, so führt dies in eine Ausnahmesituation. 13
Treiber (5) Verbindungsaufbau mit Datenbanken Ohne Treibermanager Verbindung zu DBS über direkt instanziierte Treiberobjekte aufzunehmen: und Driver dodbc = (Driver) new sun.jdbc.odbc.jdbcodbcdriver(); String url = "jdbc:odbc:kurse"; Properties p = new Properties(); p.put("user", "gast"); p.put("password", ""); Connection codbc = dodbc.connect(url, p); Driver dmsql = (Driver) new com.imaginary.sql.msql.msqldriver(); String url = "jdbc:msql://p1.inf.uni-hohenheim.de:1112/kurse"; Properties p = new Properties(); p.put("user", "gast"); p.put("password", ""); Connection cmsql = dmsql.getconnection(url, p); In allen Fällen muß zusätzlich eine Ausnahmebehandlung vorgesehen werden, denn sowohl ClassNotFoundException als auch SQLException sind möglich. 14
JDBC direkt mit Treiberklassen // Programm TreiberDirekt import sun.jdbc.odbc.*; import java.util.*; // kein import java.sql.*; public class TreiberDirekt { public TreiberDirekt() { try { JdbcOdbcDriver d = new JdbcOdbcDriver(); Properties p = new Properties(); p.put("user", "gast"); p.put("password", ""); JdbcOdbcConnection c = (JdbcOdbcConnection) d.connect("jdbc:odbc:kurse", p); JdbcOdbcStatement s = (JdbcOdbcStatement) c.createstatement(); JdbcOdbcResultSet r = (JdbcOdbcResultSet) s.executequery( "SELECT * FROM Personen WHERE nachname LIKE 'K%'"); while(r.next()) System.out.println( r.getstring("nachname") + ", " + r.getstring("vorname")); catch (Exception e) { public static void main(string[] args) { new TreiberDirekt(); // Ende class Treiberdirekt JDBC über Interfaces/Supertypen der Treiberklassen // Programm TreiberInterface import sun.jdbc.odbc.*; import java.util.*; import java.sql.*; public class TreiberInterface { public TreiberInterface() { try { Driver d = (Driver) new JdbcOdbcDriver(); Properties p = new Properties(); p.put("user", "gast"); p.put("password", ""); Connection c = (Connection) d.connect("jdbc:odbc:kurse", p); Statement s = (Statement) c.createstatement(); ResultSet r = (ResultSet) s.executequery( "SELECT * FROM Personen WHERE nachname LIKE 'K%'"); while(r.next()) System.out.println( r.getstring("nachname") + ", " + r.getstring("vorname")); catch (Exception e) { public static void main(string[] args) { new TreiberInterface(); // Ende class TreiberInterface 15