JDBC Rudolf Jansen Freiberuflicher Entwickler und Autor http://www.rudolf-jansen.de [email protected] DOAG - SIG Development 8.11.2005 © 2005, Rudolf Jansen Agenda JDBC-Treiberauswahl Oracle 10g-Treiber JDBC 4.0: Ein Ausblick © 2005, Rudolf Jansen JDBC • Java DataBase Connectivity • Zugriff auf DB über Java-API-Funktionen • Abbildung auf konkrete Datenbank durch JDBC-Treiber Portabilität (theoretisch) PreparedStatement pStmt = conn.prepareStatement( "select prs_nr, prs_vorname, prs_nachname from person where prs_nr = ?"); for( int i = 1; i<=3; i++ ){ // Parameter setzen pStmt.setInt(1, i); // Statement ausfuehren resSet = pStmt.executeQuery(); // Ergebnis ausgeben .... } © 2005, Rudolf Jansen JDBC-Treibertypen Typ 1 (JDBC-ODBC-Brücke) Zugriff über ODBC (OpenDataBaseConnectivity)-Treiber. Voraussetzung: Existenz eines ODBC-Treiber auf dem Clientrechner. Typ 2 (Native Treiber) Umwandlung in herstellerspezifische Anfragen (bei Oracle OCI) Voraussetzung: Existenz nativer Bibliotheken auf dem Clientrechner. © 2005, Rudolf Jansen JDBC-Treibertypen Typ 3 Umwandlung in herstellerunabhängiges Netzprotokoll. Voraussetzung: Datenbankhersteller unterstützt dieses Protokoll. Typ 4 (Thin-Treiber) Umwandlung in herstellerspezifisches Netzprotokoll auf Basis von Java Sockets. basieren vollständig auf Java Vorteil: keine spezielle Software auf Clientseite nötig Einsatz bei Applets © 2005, Rudolf Jansen Oracle-JDBC-Treiber OCI-Treiber (clientseitig) Zugriff über OCI-Bibliotheken (C-Routinen) Thin-Driver (clientseitig) 100 % Java Zugriff über SQL*Net-Protokoll (Basis TCP/IP) Thin-Driver (serverseitig) Zugriff aus in der Datenbank laufenden Anwendungen auf andere Datenbanken KPRB Treiber (serverseitig) Zugriff aus in der Datenbank laufenden Anwendungen Zugriff aus C-Routinen im selben Adressraum wie die SQL-Engine (Performancevorteile) © 2005, Rudolf Jansen Oracle-JDBC-Treiber JDBCNativeTreiber SQLEngine JDBCThinTreiber KPRBTreiber JDBC-ThinTreiber © 2005, Rudolf Jansen Oracle-JDBC-Treiber • Thin versus OCI • Vorteile OCI – höherer Funktionsumfang (insbesondere bei Einsatz spezieller Oracle-Features) – schneller (?) • Nachteil OCI: – erfordert bis einschl. 9i Oracle-Client-Installation auf jedem Client-Rechner • Oracle 10g: – „Instant Client“-Paket – otn.oracle.com/tech/oci/instantclient/instantclient.html – Aufnahme der Dateien in den CLASSPATH genügt – keine Client-Installation mehr nötig © 2005, Rudolf Jansen JDBC-Treiber • nicht jeder JDBC-Treiber unterstützt alle JDBC-Features • JDBC-Klasse DatabaseMetaData zur Abfrage der unterstützten Funktionen, z.B. - supportsSavepoints - supportsStatementPooling - supportsGetGeneratedKeys • JDBC-Treiber-Auswahl: http://industry.java.sun.com/products/jdbc/drivers © 2005, Rudolf Jansen JDBC-Treiber-Auswahl © 2005, Rudolf Jansen JDBC-Treiber • Zu beachten: Nicht jeder Datenbankserver unterstützt alle JDBC-Features • Beispiel: Result Sets • Ab JDBC 2.0: Scrollable ResultSets – Auch Rückwärts-Sprünge, absolute und relative Sprünge Connection.createStatement (int resultSetType, int resultSetConcurrency) – ResultSet – Typen: TYPE_FORWARD_ONLY TYPE_SCROLL_INSENSITIVE TYPE_SCROLL_SENSITIVE – Oracle: Clientseitiger Cache (Ressourcen-aufwendig) © 2005, Rudolf Jansen Oracle 10g-JDBC-Treiber Neue Features : • Connection Caching - Implicit Connection Cache - Fast Connection Failover • JDBC 3.0-Support mit Ausnahme von - Verarbeitung automatisch erzeugter Schlüssel - Result-Set Holdability - Rückgabe mehrerer Result-Sets eines JDBC-Statements • Verbesserung beim Einsatz des OCI-Treibers: - „Instant Client“-Paket - otn.oracle.com/tech/oci/instantclient/instantclient.html - Aufnahme der Dateien in den CLASSPATH genügt - keine Client-Installation mehr nötig © 2005, Rudolf Jansen JDBC-Connection-Cache • J2EE-Anwendungen – Connections werden nur kurz benötigt – kein Schließen der Verbindung – stattdessen Rückgabe in den Connection-Cache – bisher: alle Connections im Cache mit • der gleichen Datenbank und • dem gleichen DB-User Oracle 10g: – Anforderung aus RAC-Architektur: Fast Connection Failover © 2005, Rudolf Jansen Fast Connection Failover • Ausfall eines Knotens - Nachricht an den Connection-Pool - Umkonfiguration aller im Pool befindlichen Connections zu diesem Knoten • Wiederanlauf eines Knotens - Umkonfiguration zwecks Lastverteilung OracleDataSource ds = new OracleDataSource(); ds.setUser(...); ... ds.setConnectionCachingEnabled(true); ds.setFastConnectionFailoverEnabled(true); © 2005, Rudolf Jansen Oracle JDBC-Erweiterungen • zusätzliche Möglichkeiten – Umgang mit Oracle-eigenen Datentypen – Performancesteigerungen • ABER: Portabilitätsverlust • Package oracle.jdbc – ersetzt ab Oracle 9i das bisherige Package oracle.jdbc.driver – enthält u.a. folgende Klassen: OracleCallableStatement OracleConnection OracleResultSet OracleStatement OracleTypes © 2005, Rudolf Jansen JDBC 4.0 – Ziele Anpassung an aktuellen SQL-Standard SQL 2003 (insbesondere XML-Anbindung) Integration aktueller JSRs (RowSets) „Ease-Of-Development“ „Enterprise Needs“ Java 1.5 – Features (Annotations, Generics) © 2005, Rudolf Jansen JDBC 4.0 – J2SE 5 Features Annotations: Codierung über Metadaten Toolgestützte Auswertung API-Zugriff Anwendungsgebiete: - Codegenerierung (z.B. EJB, RMI) - Informationen für andere Anwendungen (z.B. Projektverwaltung) Beispiel: deprecated class Test { @Deprecated public void eineAlteMethode(){ … }; public void dieNeueMethode(){…}; } © 2005, Rudolf Jansen Datenbankzugriffe mit JDBC 4.0 Kein „DriverManager“ mehr im Sourcecode Java kümmert sich selber um JDBC-Treiber-Management Verbindungsaufbau über @Database-Annotation: @Database(type=”Oracle”, host=”localhost”,port=”4711”, user=”scott”, password=”tiger”); • Benutzerdefinierte Klasse für selektierte Daten class EmployeeResults { public String name; public String dept; public Integer salary; © 2005, Rudolf Jansen } Datenbankzugriffe mit JDBC 4.0 • Interface-Definition für Abfragen und DML interface EmployeeQueries { @Query(SQL="SELECT * FROM EMPLOYEE") EmployeeResults getAllEmployees(); @Query(SQL="SELECT * FROM EMPLOYEE WHERE salary > { sal } ") EmployeeResults getManagers(int sal); @Update(SQL="UPDATE EMPLOYEE SET salary = { sal } WHERE name = { name } ”) int changeSalary(int sal, String name); © 2005, Rudolf Jansen Datenbankzugriffe mit JDBC 4.0 Einsatz der QueryFactory AllQueries aq = QueryFactory.create (AllQueries.class); QueryFactory „verarbeitet“ @Query- und @UpdateAnnotations, d.h. „generiert“ die Datenbankzugriffe © 2005, Rudolf Jansen Datenbankzugriffe mit JDBC 4.0 Datenbankzugriff über benutzerdefinierte Klasse EmployeeResults (und Generics-Erweiterung aus J2SE 5) DataSet<EmployeeResults> rows = aq.getAllEmployees(); for (EmployeeResults elem: rows) { System.out.println(elem.name); System.out.println(elem.dept); System.out.println(elem.salary); } EmployeeResults newEmp = new EmployeeResults(); newEmp.name = “Bill Gates”; newEmp.dept = “Consulting”; newEmp.salary = new Integer(10000); rows.insert(newEmp); © 2005, Rudolf Jansen JDBC 4.0 – XML-Erweiterungen Neue XML-Features in SQL:2003 Nativer XML-Datentyp Beispiel (Oracle): create table person ( prs_nr number, prs_data XMLTYPE ); SQL/XML-Funktionen © 2005, Rudolf Jansen JDBC 4.0 – XML-Datentyp Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( „select <XMLSpalte> from tabelle …“); while(rs.next()) { XMLType xmlSpalte = (XMLType) rs.getObject(1); org.w3c.dom.Document doc=xmlSpalte.getDOM(); … } © 2005, Rudolf Jansen JDBC 4.0 – SQL/XML-Funktionen Aus SQLX-Standard xmlagg() xmlattributes() xmlconcat() xmlelement() xmlforest() Ziel: Generierung einer XML-Darstellung aus relational gespeicherten Daten © 2005, Rudolf Jansen JDBC 4.0 – SQL/XML-Funktionen Beispiel: Relationale Tabelle person_rel create table person_rel ( prs_id NUMBER; prs_vorname VARCHAR2(100); prs_nachname VARCHAR2(100); ); © 2005, Rudolf Jansen JDBC 4.0 – SQL/XML-Funktionen Select XMLELEMENT( „Person“, XMLATTRIBUTES( prs_id AS „ID“), XMLFOREST( prs_vorname, prs_nachname ) ) from person_rel; <Person ID=„1“> <PRS_VORNAME>Willi</PRS_VORNAME> <PRS_NACHNAME>Schmitz</PRS_NACHNAME> </Person> <Person ID=„2“> <PRS_VORNAME>Peter</PRS_VORNAME> <PRS_NACHNAME>Meier</PRS_NACHNAME> </Person> 2 Zeilen ausgewählt © 2005, Rudolf Jansen JDBC 4.0 – SQL/XML-Funktionen Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery( „Select XMLELEMENT( „Person“, XMLATTRIBUTES( prs_id AS „ID“), XMLFOREST( prs_vorname, prs_nachname ) ) from person_rel“); while(rs.next()) { XMLType xmlSpalte = (XMLType) rs.getObject(1); org.w3c.dom.Document doc=xmlSpalte.getDOM(); … } © 2005, Rudolf Jansen JDBC 4.0 – Weitere Features Zusatzfunktionen für Connections: - „Connection.isValid()“ - „Connection.setClientInfo()“ für Systemmonitoring (wer benutzt welche Ressourcen) - „Connection.setName()“ für exakteren Zugriff aus ConnectionPool auf eine bestimmte Connection © 2005, Rudolf Jansen Literatur • JDBC 3.0-Spezifikation: http://java.sun.com/products/jdbc/download.html#corespec30 • JDBC 4.0 Early Draft (JSR 221): http://jcp.org/en/jsr/detail?id=221 • „Java Persistenz-Strategien: Datenzugriff in Enterprise-Anwendungen: JDO, JCA, EJB, JDBC, XML“ Andreas Holubek, Rudolf Jansen, Robert Munsky, Eberhard Wolff Software&Support Verlag 400 Seiten © 2005, Rudolf Jansen