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.4 ODBC / JDBC Prinzipien Open / Java "DataBase Connectivity" Lokaler / ferner DB-Zugriff Standardisierte API Microsoft / Windows ODBC Dann Unix ODBC / JDBC DBMS Unabhängigkeit SQL DBs Treiber basiert Zugriff auf Quelle: https://de.wikipedia.org/wiki/Java_Database_Connectivity Textdatei Exceldatei RDB 5 - 2 Version 3.4 JDBC "Two-tier" Architektur für Datenzugriff Java Applikation JDBC Client Maschine DBMS-proprietäres Protokoll DBMS Quelle: Oracle JDBC Tutorial Datenbank Server RDB 5 - 3 Version 3.4 JDBC "Three-tier" Architektur für Datenzugriff 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.4 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.4 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.4 JDBC Connection Pool RDB 5 - 7 Version 3.4 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) • CLASSPATH Problem • Wird durch Maven gelöst • Siehe pom.xml Datei im JdbcPlayer Beispiel RDB 5 - 8 Version 3.4 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.4 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.4 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.4 JDBC, erstes Beispiel Verbindungsprobleme Häufige Fehler: • Error 2003: Can't connect to MySQL server => Zugriff 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 ;-) RDB 5 - 12 Version 3.4 JDBC, erstes Beispiel Datenzugriff 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.4 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.4 Key: 78, Name: Wall JDBC Java, JDBC und MySQL Typen (1) RDB 5 - 15 Quelle: https://dev.mysql.com/doc/ndbapi/en/mccj-using-clusterj-mappings.html Version 3.4 JDBC Java, JDBC und MySQL Typen (2) RDB 5 - 16 Quelle: https://dev.mysql.com/doc/ndbapi/en/mccj-using-clusterj-mappings.html Version 3.4 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"); RDB 5 - 17 Version 3.4 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.4 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.4 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.4 JDBC Grundlagen Metadaten • Wenn "ResultSet" nicht voraussehbar ist • Mehr hier: https://docs.oracle.com/javase/7/docs/api/jav a/sql/ResultSetMetaData.html • 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.4 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.4 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.4 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.4 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.4 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.4 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.4 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.4 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.4 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.4 JPA / ORM Überblick Applikation Relationale Datenbank Java Persistence API (JPA) / Object-Relation Mapping (ORM) Mehr dazu im CAS-EADJ RDB 5 - 31 Version 3.4 Übungen 1) Bringen Sie das Beispiel "JdbcTest" aus den Slides 9 bis 14 zum Laufen. a) Laden Sie die AutorBuch Datenbank von hier runter b) Importieren Sie im MySQL Workbench unter Data Import diese Datei als "Self Contained File" c) Laden Sie Java-Beispielsprojekt von hier runter d) Öffnen Sie im NetBeans mit Open Project… das Java-Beispiel Projekt e) Lesen Sie die Kommentare am Anfang der Datei JdbcTest.java 2) Erweitern Sie die Klasse "JdbcPlayerMySQL", die die "JdbcPlayerInterface" für "MeineCD" Datenbank realisiert (siehe nächste Seite). Das Java-Projekt zum Herunterladen befindet sich hier a) Öffnen Sie im NetBeans mit Open Project… das JdbcPlayer Projekt b) Passen Sie die Klasse "JcbcPlayerMySQL.java an 3) Addieren Sie und ändern Sie Daten in der Datenbank mit JdbcPlayer. RDB 5 - 32 Version 3.4 Das Programm JdbcPlayer UML Klassendiagramm Gezeichnet mit https://cacoo.com/diagrams RDB 5 - 33 Version 3.4 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.4