Relationale Datenbank

Werbung
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
Herunterladen