Tag 5 Inhaltsverzeichnis ODBC / JDBC: Ziel und Prinzip JDBC Überblick Erstes Beispiel Queries (Execute- und UpdateQuery) Der Typ "ResultSet" Diverses • Metadata • PreparedStatement • Transaktionen und Batches • JavaDB • JPA / ORM • Übungen • • • • • • RDB 5 - 1 Version 3.3 ODBC / JDBC Prinzipien Quelle: https://de.wikipedia.org/wiki/Java_Database_Connectivity RDB 5 - 2 Version 3.3 JDBC "Two-tier" Architektur für Datenzugrif Java Applikation JDBC Client Maschine DBMS-proprietäres Protokoll DBMS Quelle: Oracle JDBC Tutorial Datenbank Server RDB 5 - 3 Version 3.3 JDBC "Three-tier" Architektur für Datenzugrif Java Applet oder HTML Browser Client Maschine (GUI) HTTP, RMI, CORBA, etc... Java Applikation Server JDBC Server Maschine (Business Logik) DBMS-proprietäres Protokoll DBMS Quelle: Oracle JDBC Tutorial Datenbank Server RDB 5 - 4 Version 3.3 JDBC Komponenten • JDBC API • Teil von JavaSE & JavaEE • JDBC Driver Manager • DriverManager • DataSource + Java Naming and Directory Interface (JNDI) • JDBC Test Suite • JDBC-ODBC Bridge RDB 5 - 5 Version 3.3 JDBC Treiber Typen Java Java Application Application JDBC JDBC API API Driver Driver Manager Manager JDBC-ODBC JDBC-ODBC Bridge Bridge Driver Driver Partial Partial Java Java JDBC Driver JDBC Driver ODBC ODBC Client Client DB DB Lib Lib Pure Pure Java Java JDBC Driver JDBC Driver Pure Pure Java Java JDBC Driver JDBC Driver DB DB Middleware Middleware Client Client DB DB Lib Lib DB DB DB DB DB DB DB DB Type 1 Type 2 Type 3 Type 4 Quelle: https://de.wikipedia.org/wiki/Java_Database_Connectivity RDB 5 - 6 Version 3.3 JDBC Connection Pool RDB 5 - 7 Version 3.3 JDBC Installation Treiber für MySQL (Connector/J) • Treiber und Dokumentation auf https://dev.mysql.com/doc/connector-j/en/connectorj-installing.html • Debian / Linux Package: libmysql-java (JDBC-3.0 Type 4 driver) • Achtung: CLASSPATH setzen • Um zu kompilieren und auszuführen • z.B. /usr/bin/java/mysql.jar + /usr/bin/java/mysql-connector-java.jar RDB 5 - 8 Version 3.3 JDBC, erstes Beispiel Treiber laden public class JdbcTest { public static void main(String cmdArg[]) { try { String mysqlDriver = "com.mysql.jdbc.Driver"; Class.forName(mysqlDriver).newInstance(); // Dies lädt das Treiber... RDB 5 - 9 Version 3.3 JDBC, erstes Beispiel Verbindungsaufbau import java.sql.Connection; import java.sql.DriverManager; ... Connection con = DriverManager.getConnection ("jdbc:mysql://localhost/AutorBuch?user=gmaitre&password=Gilles"); RDB 5 - 10 Version 3.3 JDBC, erstes Beispiel Welcher Port? import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; // in mysql.jar ... MysqlDataSource ds = new MysqlDataSource(); ds.setServerName("localhost"); ds.setDatabaseName("AutorBuch"); System.out.println("Listening port:" + ds.getPortNumber()); Siehe auch /etc/mysql/my.cnf RDB 5 - 11 Version 3.3 JDBC, erstes Beispiel Verbindungsprobleme Häufige Fehler: • Error 2003: Can't connect to MySQL server => Zugrif nicht möglich, siehe my.cnf (Problem mit Hostname, Port oder DBName?) • Error 1130: Host 'xyz' is not allowed to connect to this MySQL server => Siehe mysql.user, Spalte "hostname" • Error 1045: Access denied for user 'gugus@xyz' => Falscher Name oder Passwort ;-) Quelle: Kofler S. 716 RDB 5 - 12 Version 3.3 JDBC, erstes Beispiel Datenzugrif Statement stm = con.createStatement(); ResultSet rs = stm.executeQuery("SELECT PersNr, Name FROM Autor"); while (rs.next()) { int persNr = rs.getInt("PersNr"); String name = rs.getString("Name"); System.out.println ("PersNr: " + Integer.toString(persNr) + ", Name: " + name); } RDB 5 - 13 Version 3.3 JDBC, erstes Beispiel Ende... } catch (SQLException e) { System.out.println("SQLException: " + e.getMessage()); System.out.println("SQLState: " + e.getSQLState()); System.out.println("VendorError: " + e.getErrorCode()); e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { con.close(); } catch (Exception e) { e.printStackTrace(); } } Key: 12, Name: Kemper Key: 34, Name: Kofler RDB 5 - 14 Key: 56, Name: Maitre Version 3.3 Key: 78, Name: Wall JDBC Java, JDBC und MySQL Typen (1) Quelle: https://dev.mysql.com/doc/ndbapi/en/mccj-using-clusterj-mappings.html RDB 5 - 15 Version 3.3 JDBC Java, JDBC und MySQL Typen (2) Quelle: https://dev.mysql.com/doc/ndbapi/en/mccj-using-clusterj-mappings.html RDB 5 - 16 Version 3.3 JDBC Grundlagen ExecuteQuery /** * Executes the given SQL statement, which returns a single * ResultSet object. */ ResultSet executeQuery(String sql) throws SQLException; // Beispiel ResultSet rs = stm.executeQuery ("SELECT PersNr, Name FROM Autor"); Quelle: sun-java6-source, class "java.sql.Statement" RDB 5 - 17 Version 3.3 JDBC Grundlagen ExecuteUpdate /** * Executes the given SQL statement, which may be an INSERT, * UPDATE, or DELETE statement or an SQL statement that returns * nothing, such as an SQL DDL statement. * @return either * (1) the row count for (DML) statements * (2) 0 for SQL statements that return nothing */ int executeUpdate(String sql) throws SQLException; // Beispiel int nbrOfRows = stm.executeUpdate ("update Autor set Vorname='Gilles J.F.' " + "where Vorname='Gilles';"); RDB 5 - 18 Version 3.3 JDBC Grundlagen Werte aus einem ResultSet extrahieren ResultSet rs = stm.executeQuery("SELECT PersNr, Name FROM Autor"); while (rs.next()) { int key = rs.getInt("PersNr"); String name = rs.getString("Name"); } ResultSet rs = stm.executeQuery("SELECT PersNr, Name FROM Autor"); while (rs.next()) { int key = rs.getInt(1); String name = rs.getString(2); } Anderer Weg: - getString + explizite Konvertierung - getObject + Casting RDB 5 - 19 Version 3.3 JDBC Grundlagen AUTO_INCREMENT Werte finden /** * Retrieves any auto-generated keys created as a result of * executing this Statement object. * If this Statement object did not generate any keys, * an empty ResultSet object is returned. */ ResultSet getGeneratedKeys() throws SQLException; RDB 5 - 20 Version 3.3 JDBC Grundlagen Metadaten • Wenn "ResultSet" nicht voraussehbar ist • Klasse "ResultSetMetaData" studieren (Guter Überblick mit Eclipse / JDK SourceCode) • All what you ever wanted to know about a "ResultSet"... • Es gibt auch eine Klasse DatabaseMetaData RDB 5 - 21 Version 3.3 JDBC Grundlagen 0, null und NULL • "executeQuery" gibt ein "ResultSet" zurück • Kann leer sein • next() verwenden • In einem "ResultSet" kann ein Element 0 oder NULL sein • 0 ist 0 ;-) • NULL => mit wasNull() testen RDB 5 - 22 Version 3.3 JDBC Grundlagen Navigation im ResultSet • next(), previous() • first(), last(), isFirst(), isLast() • beforeFirst(), afterLast() • getRow() • absolute(int row) // (1 <=> first; -1 <=> last) RDB 5 - 23 Version 3.3 JDBC Grundlagen PreparedStatement (1) • Wenn Abfrage mehrmals ausgeführt werden muss • Wird (eventuell) vom Server "vor-kompiliert" => effizienter • 1) Abfrageparameter mit "?" setzen • 2) Parameter mit Werten setzen und Statement ausführen RDB 5 - 24 Version 3.3 JDBC Grundlagen PreparedStatement (2) PreparedStatement ps = con.prepareStatement ("SELECT * FROM Autor WHERE Vorname= ? "); ps.setString(1, "Michael"); ResultSet rs = ps.executeQuery(); while (rs.next()) { String name = rs.getString("Name"); System.out.println("Name: " + name); } RDB 5 - 25 Version 3.3 JDBC Grundlagen Transaktionen • • • Reihenfolge von zusammengehörigen Operationen Wechsel zwischen konsistenten Zuständen Muss ACID-Eigenschaften erfüllen con.setAutoCommit(false); Statement stm = con.createStatement(); try { stm.executeUpdate ("INSERT Autor (PersNr, Name, Vorname) " + "VALUES (78, 'Wall', 'Larry')"); stm.executeUpdate ("INSERT Autor (PersNr, Name, Vorname) " + "VALUES (90, 'Schneier', 'Bruce')"); con.commit(); } catch (Exception e) { e.printStackTrace(); con.rollback(); // Nach Savepoint 'X' wäre möglich RDB 5 - 26 } Version 3.3 JDBC Grundlagen Batches Effizienter als einzelne Befehle, im Prinzip Statement stm = con.createStatement(); stm.addBatch("UPDATE stm.addBatch("UPDATE stm.addBatch("UPDATE stm.addBatch("UPDATE Autor Autor Autor Autor SET SET SET SET PersNr='21' PersNr='43' PersNr='65' PersNr='87' WHERE WHERE WHERE WHERE PersNr='12'"); PersNr='34'"); PersNr='56'"); PersNr='78'"); int [] changes = stm.executeBatch(); for (int i = 0; i < changes.length; i++) { System.out.println ("Columns changed by stm: " + i + ": " + changes[i]); } RDB 5 - 27 Version 3.3 JDBC Grundlagen Batches und Transaktionen con.setAutoCommit(false); Statement stm = con.createStatement(); try { stm.addBatch("UPDATE stm.addBatch("UPDATE stm.addBatch("UPDATE stm.addBatch("UPDATE stm.executeBatch(); con.commit(); } catch (Exception e) { e.printStackTrace(); con.rollback(); } Autor Autor Autor Autor SET SET SET SET PersNr='12' PersNr='34' PersNr='56' PersNr='78' WHERE WHERE WHERE WHERE PersNr='21'"); PersNr='43'"); PersNr='65'"); PersNr='87'"); RDB 5 - 28 Version 3.3 JDBC Grundlagen Mit BLOBs arbeiten • In Selbststudium • Ein gutes Beispiel ist hier zu finden http://www.java2s.com/Code/Java/Database-SQ L-JDBC/InsertpicturetoMySQL.htm RDB 5 - 29 Version 3.3 JavaDB Ein Überblick • Siehe http://www.oracle.com/technetwork/java/javadb/overview/index.html • Praktisch für "kleine" Projekte, die eine SQL-DB brauchen • JavaDB = Apache Derby im Java JDK integriert (separates Download) • Tools: • java -jar $DERBY_HOME/lib/derbyrun.jar sysinfo • java -jar $DERBY_HOME/lib/derbyrun.jar ij • java -jar $DERBY_HOME/lib/derbyrun.jar dblook -d 'jdbc:derby:firstdb' RDB 5 - 30 Version 3.3 JPA / ORM Überblick Applikation Relationale Datenbank Java Persistence API (JPA) / Object-Relation Mapping (ORM) Mehr dazu im CAS-EADJ RDB 5 - 31 Version 3.3 Übungen 1) Bringen Sie das Beispiel "JdbcTest" aus den Slides 9 bis 14 zum Laufen. 2) Laden "JdbcPlayer" runter und implementieren Sie die Klasse "JdbcPlayerMySQL", die die "JdbcPlayerInterface" für "MeineCD" Datenbank realisiert (siehe nächste Seite). Die Software befindet sich hier: http://www.sws.bfh.ch/maitre/SD-RDB/JdbcPlayer.zip a) "JdbcPlayer"-Projekt in Eclipse laufen lassen b) In der Datei JdbcPlayer.java, die Zeile 16 als Kommentar markiere und die Zeile 17 das Kommentar ausnehmen c) Die Klasse "JcbcPlayerMySQL.java.template" in "JcbcPlayerMySQL.java" umbenennen und anpassen. 3) Addieren Sie und ändern Sie Daten in der Datenbank mit JdbcPlayer. RDB 5 - 32 Version 3.3 Das Programm JdbcPlayer UML Klassendiagramm Gezeichnet mit https://cacoo.com/diagrams RDB 5 - 33 Version 3.3 Das Programm JdbcPlayer Anwendungsbeispiel JdbcPlayer Command Interpreter V1.2 ----------------------------------Type 'help' to list the commands JdbcPlayer> help List of available commands (case-insensitive) --------------------------------------------connect "<jdbcConnectionString>" disconnect show Tables execute query "<QueryString>" execute update "<UpdateString>" exit help JdbcPlayer> connect "jdbc:mysql://localhost/AutorBuch?user=...&password=..." INFO: New connection eshtablished JdbcPlayer> execute query "select * from Autor" |--------------------|--------------------|--------------------| | PersNr | Vorname | Name | |--------------------|--------------------|--------------------| | 12 | Alfons | Kemper | | 34 | Michael | Kofler | | 56 | Gilles | Maitre | | 78 | Larry | Wall | |--------------------|--------------------|--------------------| JdbcPlayer> exit RDB 5 - 34 Version 3.3