Rückblick Datenbankschnittstellen erlauben Zugriff auf Datenbank aus einer externen Anwendung Portabilität als wichtige Anforderung, d.h. RDBMS oder Programmiersprache soll leicht austauschbar sein Call-Level Interfaces als Schnittstellen für bestimmtes RDBMS und bestimmte Programmiersprache Open Database Connectivity (ODBC) erreicht Entkopplung durch Verwendung von Treibern Java Database Connectivity (JDBC) für Java-Code 42
Transaktionskontrolle Beim Ausführen des ersten SQL-Kommandos über eine Verbindung (Connection) wird implizit eine neue Transaktion begonnen Festschreiben (commit) oder Zurückrollen (rollback) der Transaktion ist mit folgenden Kommandos möglich 1 conn.commit(); // im try 1 conn.rollback(); // im try 43
Transaktionskontrolle Verbindung kann auf automatisches Festschreiben (auto commit) umgestellt werden, so dass jedes SQL-Kommando direkt festgeschrieben wird 1 conn.setautocommit(true); Achtung: Bei einigen Treibern ist dies die Voreinstellung; ggf. empfiehlt es sich zuerst den aktuellen Wert mittels getautocommit auszulesen 44
Transaktionskontrolle Isolationsstufe der Verbindung kann gesetzt werden mit der Methode settransactionisolation, welche eine der folgenden Konstanten als Parameter erwartet Connection.TRANSACTION_READ_UNCOMMITTED Connection.TRANSACTION_READ_COMMITTED Connection.TRANSACTION_REPEATABLE_READ Connection.TRANSACTION_SERIALIZABLE 45
Fehlerbehandlung (SQLException) SQLException als Ausnahmeklasse für alle Fehler z.b. beim Verbindungsaufbau oder inkorrektem SQL 1 Connection conn = null; 2 Statement stmt = null; 3 ResultSet rs = null; 4 try { 5... 6 } catch (SQLException sqle) { 7 System.out.println(" Fehler: " + sqle.getmessage()); 8... // Fehlerbearbeitung 9 } finally { 10 if (rs!= null) try {rs.close();} catch (SQLException sqle) {}; 11 if (stmt!= null) try {stmt.close();} catch (SQLException sqle) {}; 12 if (conn!= null) try {conn.close();} catch (SQLException sqle) {}; 13 } Schließen aller JDBC-Objekte, um Ressourcen auf Client (z.b. RAM) oder Server (z.b. Sockets) freizugeben 46
Vorkompiliertes SQL (PreparedStatement) Anwendungen führen oft zahlreiche SQL-Kommandos gleicher Bauart auf dem RDBMS via JDBC aus Einfügen von Datensätzen mittels INSERT 1 INSERT INTO Studenten (MatrNr, Vorname, Name) VALUES (?,?,?) Anfragen mit Primärschlüssel als Selektionsprädikat 1 SELECT * FROM Studenten WHERE MatrNr =? Isolierte Ausführung jedes der baugleichen SQL- Kommandos ist teuer, da das RDBMS jedes SQL-Kommando erneut parsen muss jedes SQL-Kommando Netzwerkkommunikation erfordert 47
Vorkompiliertes SQL (PreparedStatement) Vorkompiliertes SQL bietet Möglichkeit, baugleiche SQL- Kommandos in einer Art Schablone zusammenzufassen das SQL-Kommando muss so nur einmal geparst werden beim Einfügen können Gruppen (batches) von Zeilen auf einmal, mit einer Netzwerkkommunikation, eingefügt werden JDBC stellt mit der Klasse PreparedStatement eine Klasse bereit, die solches vorkompiliertes SQL erlaubt 48
Vorkompiliertes SQL (PreparedStatement) Beim Anlegen eines PreparedStatements können mittels? Platzhalter definiert werden, die dann vor Ausführung durch konkrete Werte ersetzt werden 1 PreparedStatement pstmt = null; // vor try 2 pstmt = conn.preparestatement(" SELECT MatrNr, Name, Vorname " + 3 " FROM Studenten WHERE MatrNr =?"); Ersetzen der Platzhalter und Ausführen des Kommandos 1 long matrnr = 32781; 2 pstmt.setlong(1, matrnr); 3 rs = pstmt.executequery(); 49
Vorkompiliertes SQL (PreparedStatement) Bei Verwendung eines PreparedStatement für INSERT Kommandos können zudem einzufügende Zeilen zu Gruppen (batches) zusammengefasst werden 1 PreparedStatement pstmt = null; // vor try 2 3 // Liste mit allen Studenten 4 LinkedList <Student > studenten =...; 5 6 // PreparedStatement anlegen 7 String insert = " INSERT INTO Studenten VALUES ( MatrNr, Vorname, Name) " + 8 " VALUES (?,?,?)" 9 pstmt = conn.preparestatement(insert); 10 11 // Einzufügende Zeilen vorbereiten 12 for(student : studenten) { 13 pstmt.set(1, student.getmatrnr()); 14 pstmt.set(2, student.getvorname()); 15 pstmt.set(3, student.getname()); 16 pstmt.addbatch(); 17 } 18 19 // Batch ausfü hren 20 pstmt.executebatch(); 50
Vorkompiliertes SQL (PreparedStatement) Achtung: Aktueller Batch wird im RAM des Clients zwischengespeichert; bei sehr großen Batches sollte ggf. executebatch regelmäßig nach bestimmter Anzahl hinzugefügter Zeilen aufgerufen werden 51
Vergleich Statement vs. PreparedStatement Code zum Download auf Website zur Vorlesung 1 CREATE TABLE dummy ( 2 a int, 3 b int, 4 c int 5 ) Einfügen von 1.000.000 Zeilen per Statement und PreparedStatement in SQLite auf aktuellem Rechner (SSD, i7, 8GB RAM) Dauer mit Statement: 18 Sekunden Dauer mit PreparedStatement: 6 Sekunden 52
Ergebnis (ResultSet) Jeder Aufruf von next einer Instanz von ResultSet liest die jeweils nächste Zeile aus dem Ergebnis Je nach JDBC-Treiber bedeutet jeder Aufruf zudem eine Netzwerkkommunikation, d.h. jede Zeile wird separat vom RDBMS übertragen Viele JDBC-Treiber bieten die Möglichkeit der Pufferung, d.h. Zeilen werden in Gruppen übertragen und im RAM des Clients zwischengespeichert Zahl der zu puffernden Zeilen lässt sich mittels der Methode setfetchsize einstellen 53
11.5 Objekt-Relationale Abbildung (ORM) Objekt-orientierter Entwurf (z.b. mit UML) führt zu Klassen (z.b. Student und Vorlesung) mit Attributen (z.b. Name oder Titel) Assoziationen (z.b. Student hört Vorlesung) Methoden, die Geschäftslogik erfassen (z.b. Anmelden eines Student zu einer Vorlesung) Instanzen der Klassen sollen dauerhaft (persistent) in einem RDBMS im Hintergrund, abgelegt werden 54
Objekt-Relationale Abbildung (ORM) Frameworks zur objekt-relationalen Abbildung (object relational mapping) automatisieren die Erstellung entsprechenden Codes zum Lesen/Speichern der Instanzen sowie zum Anfragen z.b. Enterprise Java Beans in Java EE Java Data Objects und Java Persistence API Hibernate Relationale Datenbank im Hintergrund kann mittels ORM verborgen werden, so dass Entwickler auch ohne SQL-Kenntnisse mit den Daten arbeiten können 55
Objekt-Relationale Abbildung (ORM) ekt-relationales Mapping: Prinzip Applikation Laufzeitsystem Datenbankschema Abbildungsvorschrift Anwendungsobjekte Objektmodell Quelle: Saake, Sattler und Heuer [2] 56
Objektorientierter Entwurf vs. Relationenmodell Beispiel: Klassen in Hochschulanwendung 1 public class Student { 2 // Attribute 3 private long matrnr; 4 private String vorname; 5 private String name; 6 private int semester; 7 private List<Vorlesung > hört; 8 9 // Konstruktor 10 public Student() {...}; 11 12 // Methoden 13 public void setmatrnr(long matrnr) {...} 14 public long getmatrnr() {...} 15 public void addvorlesung(vorlesung vorlesung) {...} 16... 17 } 57
Objektorientierter Entwurf vs. Relationenmodell Beispiel: Klassen in Hochschulanwendung 1 public class Vorlesung { 2 // Attribute 3 private long vorlnr; 4 private String titel; 5 private List<Student > hörer; 6 private Professor gelesenvon; 7 8 // Konstruktor 9 public Vorlesung() {...}; 10 11 // Methoden 12 public void setvorlnr(long vorlnr) {...} 13 public long getvorlnr() {...} 14 public void addstudent(student student) {...} 15... 16 } 58
Objektorientierter Entwurf vs. Relationenmodell Beispiel: Klassen in Hochschulanwendung 1 public class Professor { 2 // Attribute 3 private long persnr; 4 private String vorname; 5 private String name; 6 private String fach; 7 private Büro int; 8 9 // Konstruktor 10 public Professor() {...}; 11 12 // Methoden 13 public void setpersnr(long persnr) {...} 14 public long getpersnr() {...} 15... 16 } 59
Objektorientierter Entwurf vs. Relationenmodell Wie lassen sich Klassen mit ihren Attributen und Assoziationen auf Relationen abbilden? Idee: Jede Klasse wird auf eine Relation abgebildet Professor +PersNr : int +Vorname : String +Name : String +Fach : String +Büro : int Professoren : Ó Ô [ PersNr : long, Vorname : string, Name : string, Fach : string, Büro : integer ] Problem: Relationale Normalformen werden verletzt z.b. mengenwertige Attribute (z.b. hörer in Vorlesung) Redundanz als Ergebnis von 1:n und n:n Assoziationen 60
Objektorientierter Entwurf vs. Relationenmodell Klassen und ihre Assoziationen müssen u.u. auf mehr als eine einzelne Relation abgebildet werden 1:1 Assoziation als Fremdschlüsselattribut 1:n Assoziation als Fremdschlüsselattribut oder als Fremdschlüsseltabelle n:m Assoziation als Fremdschlüsseltabelle Assoziationen mit Attributen auf Fremdschlüsseltabelle vgl. Übersetzung von ERM-Diagrammen in Relationen wie in Kapitel 2 besprochen 61
Hibernate Hibernate (http://hibernate.org) ist ein populäres Java- Framework für objekt-relationale Abbildung Hibernate erhält Java-Klasse mit Abbildungsvorschrift (in XML-Datei) und kann damit Instanzen in Datenbank speichern und sie von dort lesen Bei Navigation entlang von Assoziationen werden die verbundenen Instanzen aus der Datenbank geholt (z.b. die Studenten bei Zugriff auf hörer in Vorlesung) 62
Hibernate Abbildungsvorschrift in XML Klasse muss bestimmte Anforderungen erfüllen, z.b. leeren Konstruktor haben sowie get- und set-methoden für alle Attribute Beispiel: Abbildungsvorschrift für Professor 1 <hibernate-mapping> 2 <class name=" Professor" table=" Professoren"> 3 <id name=" persnr"> 4 <generator class=" native" /> 5 </id> 6 <property name=" name" /> 7 <property name=" vorname" /> 8 <property name=" fach"/> 9 <property name="büro" /> 10 </class > 11 </hibernate -mapping > 63
Speichern von Daten mit Hibernate Instanz von Klasse wird angelegt und Attribute gesetzt 1 Transaction tx = null; 2 3 // Professor anlegen 4 Professor professor = new Professor(); 5 professor.setpersnr(31415); 6 professor.setvorname(" Albert"); 7 professor.setname(" Einstein"); 8 professor.setbüro(412); 9 10 // Professor speichern 11 try { 12 tx = session.begintransaction(); 13 session.save(professor); 14 tx.commit(); 15 } catch (HibernateException he) { 16 if (tx!= null) tx.rollback(); 17 } session vorab mit Verbindungsparametern initialisiert 64
Anfragen mit Hibernate Hibernate unterstützt zudem verschiedene Arten von Anfragen, die keine SQL-Kenntnisse erfordern eigene leichtgewichtige Anfragesprache HQL mittels Beispielinstanz (query by example) basierend auf Kriterien (query by criteria) 65
Anfragen mit HQL Hibernate hat eigene einfache Anfragesprache HQL, deren Anfragen sich auf die Namen und Attribute der Java-Klassen beziehen (nicht auf Relationen) 1 // Anfrage formulieren 2 Query query = 3 session.createquery(" from Professor where Name = Einstein "); 4 5 // Ergebnisse lesen 6 Iterator iter = query.iterate(); 7 while (iter.hasnext()) { 8 Professor professor = (Professor) iter.next(); 9 } 66
Anfragen mit Beispielinstanz (query by example) Bei Anfragen mit Beispielinstanz wird eine Instanz erzeugt, deren Attribute die gewünschten Werte haben 1 // Beispielinstanz anlegen 2 Professor professor = new Professor(); 3 professor.setname(" Einstein"); 4 5 // Ergebnisse als Liste 6 List<Professor > result = session.createcriteria(professor.class) 7.add(Example.create(professor)).list(); 67
Anfragen mit Kriterien (query by criteria) Anfrage kann durch Angabe von Kriterien mittels Methodenaufrufen erzeugt werden 1 // Ergebnisse als Liste 2 List<Professor > res = session.createcriteria(professor.class) 3.add(Restrictions.eq(" Name", " Einstein" )).list(); 68
Navigation entlang Assoziationen in Hibernate Bei Navigation entlang Assoziationen (d.h. Zugriff auf Attribute, die auf andere Attribute verweisen), werden die entsprechenden Instanzen automatisch geladen Beispiel: Vorlesungen von Student mit MatrNr 38762 1 // Anfrage formulieren 2 Query query = 3 session.createquery(" from Student where MatrNr = 38762"); 4 5 // Student lesen 6 Student student = (Student) query.list().get(0); 7 8 // Vorlesungstitel ausgeben 9 for (Vorlesung vorlesung : student.getvorlesungen()) { 10 System.out.println(vorlesung.getTitel()); 11 } 69
Ändern von Daten in Hibernate Hibernate erlaubt es, Änderungen an Attributwerten von Instanzen zurück in die Datenbank zu schreiben Beispiel: Erhöhe Semester aller Studenten 1 // Transaktionsanfang 2 Transaction tx = session.begintransaction(); 3 4 // Anfrage formulieren 5 Query query = 6 session.createquery(" from Studenten"); 7 8 // Ergebnisse lesen 9 Iterator iter = query.iterate(); 10 while (iter.hasnext()) { 11 Student student = (Student) iter.next(); 12 student.setsemester(student.getsemester() + 1); 13 } 14 15 // Ä nderungen festschreiben 16 tx.commit(); 70
Zusammenfassung JDBC erlaubt Transaktionskontrolle, d.h. Festschreiben und Zurückrollen sowie setzten der Isolationsstufe Vorkompiliertes SQL beschleunigt die Ausführung mehrerer Kommandos gleicher Bauart signifikant Objekt-relationale Abbildung speichert Instanzen von Klassen in relationale Datenbank; kann Datenbank und SQL vor den Entwicklern verbergen Hibernate als populäres Java-Framework für objekt-relationale Abbildung 71
Literatur [1] A. Kemper und A. Eickler: Datenbanksysteme Eine Einführung, De Gruyter Oldenbourg, 2013 [2] G. Saake, K.-U. Sattler und A. Heuer: Datenbanken - Konzepte und Sprachen, mitp Professional, 2013 (Kapitel 13) 72