Kapitel 5 SQL und Java Flien zum Datenbankpraktikum Wintersemester 2012/13 LMU München 2008 Thmas Bernecker, Tbias Emrich 2010 Tbias Emrich, Erich Schubert unter Verwendung der Flien des Datenbankpraktikums aus dem Wintersemester 2007/08 vn Dr. Matthias Schubert
Übersicht 5.1 SQL-Unterstützung in Java 5.2 Java Database Cnnectivity 5.3 Embedded SQL in Java 5.4 Java Stred Prcedures LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 2
Überblick über Java in Oracle Auf SQL-Daten kann in Java über JDBC (und SQLJ) zugegriffen werden. Java Stred Prcedures: Es ist möglich, Java-Prgramme vn PL/SQL aus und PL/SQL-Przeduren vn Java aus zu starten. Entwicklung verteilter Anwendungen mit Object Request Brkern (ORB/CORBA) und der Unterstützung durch Enterprise Java Beans (EJB) (wird hier nicht besprchen). Realisierung dynamischer HTML-Seiten durch Servlets und Java Server Pages möglich Als Persistent Strage über Object-Relatinal-Mapping (ORM), z.b. mit Hibernate. LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 3
RDBMS und Java Sftware-Entwicklung in Java wird in Oracle über flgende Schnittstellen unterstützt: Java Database Cnnectivity (JDBC): Klassenbiblithek zum kmfrtablen dynamischen Zugriff auf eine (bjekt-)relatinale Datenbank aus Java heraus. Embedded SQL in Java (SQLJ): Erlaubt die direkte Integratin vn statischem SQL in Java hne Benutzung einer Klassenbiblithek. Setzt meist auf JDBC auf und kann mit JDBC kmbiniert werden. Datenbank-Zugriffe sind clientseitig (Java Applikatinen und Applets) und serverseitig (Java Stred Prcedures) möglich. Für letztere bietet der Oracle Server eine Laufzeitumgebung (JServer) und persistente Verwaltung an, ähnlich zu den Stred Prcedures in PL/SQL. Standards Versin Oracle 11g unterstützt Java ab Versin 1.5 und JDBC 4.0 Versin Oracle 10g unterstützt Java ab Versin 1.4 und JDBC 3.0 Versin Oracle 9i unterstützt Java ab Versin 1.3 und JDBC 2.0 LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 4
Übersicht 5.1 SQL-Unterstützung in Java 5.2 Java Database Cnnectivity 5.3 Embedded SQL in Java 5.4 Java Stred Prcedures LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 5
JDBC: Aufbau einer Datenbank-Verbindung (clientseitig) Anmelden der benötigten Packages: imprt java.sql.*; // JDBC-Package Die Packages racle.jdbc.driver.* und racle.sql.* können außerdem für die Verwendung vn Erweiterungen "imprtiert" werden. Dazu $ORACLE_HOME/jdbc/lib/jdbc14.jar in den CLASSPATH legen. JDBC-Treiber laden: Oracle bietet zwei clientseitige JDBC-Treiber an: OCI und Thin. Diese müssen einmalig im Prgramm registriert werden: DriverManager.registerDriver(new racle.jdbc.driver.oracledriver()); Verbindung öffnen (OCI-Client): Wenn ein OCI-Client (Oracle Call Interface) installiert ist, sllte man den schnellen JDBC-OCI-Treiber benutzen. Da dieser plattfrmabhängig ist, funktiniert er allerdings nicht bei Applets. Cnnectin cnn = DriverManager.getCnnectin ("jdbc:racle:ci:@flres.dbs.ifi.lmu.de:1521:dbprakt","user","passwrd"); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 6
Verbindung öffnen (Thin-Client): Der JDBC-Thin-Treiber hingegen ist plattfrmunabhängig. Eine Verbindung flgendermaßen aufgebaut: Aus einer Applikatin: Cnnectin cnn = DriverManager.getCnnectin ("jdbc:racle:thin:@flres.dbs.ifi.lmu.de:1521:dbprakt","user","passwrd"); Aus einem signierten Applet: imprt netscape.security.*;... PrivilegeManager.enablePrivilege("UniversalCnnect"); Cnnectin cnn = DriverManager.getCnnectin ("jdbc:racle:thin:user/passwrd@ flres.dbs.ifi.lmu.de:1521:dbprakt");... PrivilegeManager.revertPrivilege("UniversalCnnect"); Applet Security: Aufgrund der Hst f rigin -Plitik des Java Sicherheitsmdells dürfen unsignierte Applets nur auf den WWW- Server zugreifen vn dem sie heruntergeladen wrden sind. LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 7
JDBC: Aufbau einer Datenbank-Verbindung (serverseitig) Über den Oracle JServer können Java Methden auch im Datenbankserver gespeichert und ausgeführt werden (Java Stred Prcedures). Für den serverseitigen JDBC-Treiber und Verbindungsaufbau sind einige Besnderheiten zu beachten. Cnnectin cnn = DriverManager.getCnnectin("jdbc:default:cnnectin"); Siehe dazu: Oracle Dcumentatin Library, JDBC Develper's Guide and Reference, Kap. 1, Abschnitt: Server-Side Basics. LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 8
Absetzen und Verarbeiten vn SQL-Anfragen Instanziieren vn Anweisungen: Auf einer ffenen Verbindung cnn werden Statement-Objekte instanziiert, um SQL- Anweisungen an das DBS zu senden. Statements können wiederverwendet werden: Statement stmt = cnn.createstatement(); Anfragen absetzen: Über das Statement-Objekt stmt kann nun z.b. eine Anfrage abgesetzt werden: ResultSet rset = stmt.executequery ("SELECT * FROM mytable"); Ergebnisse verarbeiten: Abhängig vm Datentyp <Type> der Spalte <cl_nr> können nun die Ergebnisse tupelweise aus dem ResultSet rset (Cursr!) ausgelesen werden: while (rset.next()) System.ut.println (rset.get<type>(<cl_nr>)); Objekte nach Gebrauch schließen (Reihenflge beachten!): rset.clse(); stmt.clse(); cnn.clse(); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 9
Eine kleine Anfrage: imprt java.sql.*; class Emplyee { public static vid main (String args []) thrws SQLExceptin { DriverManager.registerDriver(new racle.jdbc.driver.oracledriver()); Cnnectin cnn = DriverManager.getCnnectin ("jdbc:racle:ci:@dbprakt", "sctt", "tiger"); Statement stmt = cnn.createstatement(); ResultSet rset = stmt.executequery("select * frm all_users"); while (rset.next()) System.ut.println(rset.getString(1)); rset.clse(); stmt.clse(); cnn.clse(); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 10
Verarbeiten vn ResultSets Navigatin: Der Cursr kann mit der Methde next() des ResultSets geprüft und weitergesetzt werden. JDBC ab Versin 2.0 erlaubt bereits eine weitgehend freie Psitinierung des Cursrs im ResultSet. Datentypen: Mit den get<type>()-methden werden die Ergebnisse spaltenweise eingelesen. Die Java-Variablen müssen dabei zu den JDBC-Datentypen kmpatibel sein. Die Spalten werden dabei entweder durch ihre Psitin (beginnend mit 1) der durch ihren Namen (als String) identifiziert. INTEGER FLOAT DOUBLE DECIMAL CHAR VARCHAR DATE getint getflat getduble getbigdecimal getstring getdate Kmbinatinen: rt: empfhlen schwarz: möglich LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 11
Verwendung vn Platzhaltern: Platzhalter: entweder als? der benannt als :name (SQLJ) Beispiel: PreparedStatement pstmt = cnn.preparestatement("delete frm test where cl =?"); pstmt.setstring(1,"a"); pstmt.executeupdate(); Vrteile: Weniger Stringperatinen und Parsing-Aufwand Optimierung durch DBMS Weniger Fehleranfällig (String-Serialisierung, Snderzeichen!) Weniger Sicherheitsprbleme (SQL Injectin!) Verwenden bei: Häufigen Statements (wegen Optimierung) Variablen, unsicheren Werten (Fehler, Sicherheit) LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 12
Weitere SQL-Anweisungen DDL-Befehle: stmt.executeupdate("create table test(cl varchar2(10))"); stmt.executeupdate("drp table test"); Einfügen, Ändern und Löschen vn Daten: stmt.executeupdate("insert int test values ( A )"); stmt.executeupdate("update test set cl= B where cl= A "); stmt.executeupdate("delete frm test where cl = B "); Vrcmpilierte Anweisungen: PreparedStatement pstmt = cnn.preparestatement("delete frm test where cl =?"); pstmt.setstring(1,"a"); pstmt.executeupdate(); Aufrufen vn Stred Prcedures: CallableStatement cstmt = cnn.preparecall("{ call prc(?) "); cstmt.setint(1,var); cstmt.executeupdate(); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 13
Allgemeine SQL-Anweisungen: Wenn der Typ der SQL-Anweisung (select, insert, create,...) erst zur Laufzeit bekannt ist, kann man die allgemeinere execute()-methde verwenden: String runtime_stmt;... if (stmt.execute(runtime_stmt)) { rset = stmt.getresultset();... // runtime_stmt war eine Anfrage else if (stmt.getupdatecunt() > 0) { // runtime_stmt war ein insert-, update- der delete-befehl... else { // runtime_stmt hat keinen Rueckgabewert (z.b. DDL)... LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 14
Transaktinen Aut-Cmmit: Standardmäßig wird jede SQL-Anweisung, die über ein Statement abgesetzt wird, als eigenständige Transaktin betrachtet. Wenn mehrere DML- Anweisungen in einer Transaktin geblckt werden sllen, muss man den Aut-Cmmit-Mdus abstellen: cnn.setautcmmit(false); Aut-Cmmit kann reaktiviert werden mit: cnn.setautcmmit(true); Cmmit Transactin: cnn.cmmit(); Rllback Transactin: cnn.rllback(); Daneben gibt es eine Fülle vn Erweiterungen, z.b. zur Verwaltung vn Batch Updates der des Islatin Levels einer Transaktin. LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 15
Fehlerbehandlung Exceptins: JDBC macht Fehlersituatinen des DBMS über Java Exceptins sichtbar: try { // Cde, der eine SQL-Exceptin erzeugt catch(sqlexceptin ex) { Warnings: System.err.println("SQLExceptin: " + ex.getmessage()); Instanzen vn Cnnectin, Statement und ResultSet können SQL-Warnmeldungen erzeugen. Diese werden mit der Methde getwarning() sichtbar: SQLWarning warn = stmt.getwarnings(); if (warn!= null) { System.ut.println("SQLWarning: " + warn.getmessage()); Warnungen unterbrechen den nrmalen Prgrammlauf nicht. Sie machen auf mögliche Prblemfälle aufmerksam (z.b. DataTruncatin). LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 16
Übersicht 5.1 SQL-Unterstützung in Java 5.2 Java Database Cnnectivity 5.3 Embedded SQL in Java 5.4 Java Stred Prcedures LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 17
Embedded SQL in Java: SQLJ Entwicklungs- und Laufzeitumgebung zur Einbettung statischer SQL-Befehle in Java Kmpnenten vn SQLJ: SQLJ Translatr: Präcmpiler, der SQLJ-Cde (*.sqlj) in Java Quellcde (*.java) umwandelt und anschließend autmatisch in Java Bytecde cmpiliert (*.class). Aufruf: sqlj <prg>.sqlj SQLJ Runtime: JDBC-basierende Laufzeitumgebung für kmpilierte (*.class) SQLJ-Prgramme. Die SQLJ Runtime Packages werden autmatisch zur Laufzeit benutzt. Aufruf: java <prg> Installatin vn SQLJ: Sämtliche SQLJ-Klassen (100% Java-Cde) befinden sich in der Biblithek $ORACLE_HOME/sqlj/lib/translatr.zip (in den CLASSPATH legen). LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 18
Ein kleines Beispiel: imprt java.sql.*; imprt sqlj.runtime.*; imprt sqlj.runtime.ref.*; #sql iteratr UserIter(String, Lng, Date); public class SqlJ { public static vid main(string argv[]) thrws SqljExceptin { DefaultCntext cx1 = Oracle.getCnnectin("jdbc:racle:ci:@dbprakt, user", pass", true); DefaultCntext.setDefaultCntext(cx1); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 19
UserIter iter; String username = null; Lng user_id = null; #sql iter = { SELECT username, user_id FROM all_users ; #sql {FETCH :iter INTO :username, :user_id; // retrieve and display the result frm the SELECT statement while (!iter.endfetch()) { //TODO d smething with the current tuple #sql {FETCH :iter INTO :username, :user_id; iter.clse(); db.discnnect(); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 20
Übersicht 5.1 SQL-Unterstützung in Java 5.2 Java Database Cnnectivity 5.3 Embedded SQL in Java 5.4 Java Stred Prcedures LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 21
Java Stred Prcedures: Eigenschaften Die Oracle Java Virtual Machine ist eigene JVM im DB-Server. Kmpnenten wie Garbage Cllectin und Class Lader sind auf die Serverumgebung abgestimmt. Prinzipiell sind alle Java-Methden aufrufbar (Ausnahme: GUI-Prgramme). D.h. Java Stred Prcedures als Functins, Prcedures, Trigger, PL/SQL- Unterprgramme und Packages. Objektrelatinale User-Defined Datatypes (siehe Kapitel 6) können ebenfalls unter Java angesprchen werden. Die geschieht über explizites Mapping der über das Interface Struct, das ein Standard-Mapping bereitstellt. Java-Klassen können vn PL/SQL und SQL aus angesprchen werden. Hierzu müssen die Klassen über sgenannte Call Specs im Data-Dictinary publiziert werden. LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 22
Beispiel: Erstellen einer Java Stred Prcedure SQL> create r replace and cmpile java surce named USERMANAGER as imprt java.sql.*; public class UserManager { public static String sampleuser() thrws SQLExceptin { / DriverManager.registerDriver( new racle.jdbc.driver.oracledriver() ); Cnnectin cnn = DriverManager.getCnnectin("jdbc:default:cnnectin"); Statement statement = cnn.createstatement(); ResultSet results = statement.executequery("select * frm all_users ); if( results.next() ) { return results.getstring(1); return new String("n user yet ); LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 23
Für Methden die in Oracle direkt aufgerufen werden sllen werden Call Specs angelegt. Dies ist nur für Tp-Level-Methden erfrderlich. Klassen die vn anderen Klassen verwendet werden brauchen nicht publiziert werden. SQL> create r replace functin SAMPLEUSER return VARCHAR2 as 2 language java name UserManager.sampleuser () return java.lang.string'; 3 / Functin created. Aufruf der Methde SQL> variable mystring varchar2[20]; SQL> exec :mystring := SAMPLEUSER(); Call cmpleted. SQL> print mystring; MYSTRING --------------------------------------- USER1 LMU München Flien zum Datenbankpraktikum Wintersemester 2012/13 24