DBPR2

Werbung
Datenbankprogrammierung 2
JDBC






Java Database Connectivity
Call Level Interface
Schnittstelle zwischen DBMS und Applikation
JDBC API ist seit JDK1.1 inkludiert
Ermöglicht Zugriff aus Java-Applikationen auf Datenbanken
Unterstützt dynamisches SQL
two-tier architecture
three-tier architecture
Wichtigste Klassen

Im Package java.sql zusammengefasst:

java.sql.DriverManager:

java.sql.Connection:
java.sql.Statement:

java.sql.ResultSet:

Laden der Treiber, Verbindung zur
DB
Repräsentiert DB-Verbindung
Ermöglicht Ausführung von SQLAnweisungen über gegebene
Verbindung
Verwaltet Ergebnisse einer
Anfrage in Form einer Relation
und unterstützt Zugriff auf
einzelne Spalten
JDBC: Prinzipielle Schritte
1.Aufbau einer Verbindung zur
Datenbank
2.Senden einer SQL-Anweisung
3.Verarbeiten der Anfrageergebnisse
Aufbau einer Verbindung zur
Datenbank
1. Laden des JDBC Treibers:


Entweder explizit im Programm:
Class.forName(“oracle.jdbc.OracleDriver”);
oder in System-Property sql.drivers
2. Herstellen einer Verbindung:
Connection con = DriverManager.getConnection
(“jdbc:oracle:[email protected]
:1521:xe”,”gruppeX”,”passwort”);
JDBC URL
Bsp.:
jdbc:oracle:thin:@gutemine.ict.tuwien.ac.at:1521:xe



oracle:thin ... Treibername
gutemine.ict.tuwien.ac.at:1521 ... Host
xe ... Name der Datenbank
Senden einer SQL-Anweisung
Datenbankabfrage:
String query = “SELECT Titel FROM Buch”;
Statement stmt=con.createStatement();
ResultSet result=stmt.executeQuery(query);
Datenbankänderung:
String update = “INSERT INTO Buch VALUES(...)”;
Statement stmt=con.createStatement();
ResultSet result=stmt.executeUpdate(update);
ResultSet






ResultSet Interface bietet Methoden zum Abfragen
und Ändern von Resultaten
Ergebnismenge ist eine Tabelle auf die zeilenweise
und spaltenweise zugegriffen werden kann
Cursorbewegungen: next(), previous(), first(),
absolute(int row), ...
Achtung: Interner Cursor ist vor dem ersten Tupel
positioniert, d.h. bevor ein Tupel gelesen wird, muss
next() aufgerufen werden
Abfragen: getString(“Titel”), getBoolean(1), ...
Änderungen: updateString(...), updateBoolean(...), ...
DB-Änderung mit Java-Befehlen statt
SQL-Befehlen
String query = “SELECT Titel, Preis FROM Buch”;
Statement stmt=con.createStatement();
ResultSet result=stmt.executeQuery(query);
result.last();
result.updateFloat(“Preis”, 19.90);
result.updateRow();



Update Operationen betreffen Zeile, in der sich der Cursor
gerade befindet
updateFloat(), updateString(), ... wirken sich nur auf ResultSet
aus
updateRow(), insertRow(), deleteRow() bewirken Änderung der
Datenbank
Verarbeiten der Anfrageergebnisse
while(result.next()){
System.out.println(result.getString(“Ort”);
System.out.println(result.getString(1);//1. Spalte
}
Fehlerbehandlung
try {
//Aufruf von JDBC-Anweisungen, die möglicherweise
//Exceptions erzeugen
} catch(SQLException exc) {
System.out.println(“SQLException:” + exc.getMessage());
}
Transaktionen





Werden über Methoden der Klasse java.sql.connection realisiert
Nach Aufbau einer Verbindung zur DB: Auto-Commit-Modus
Änderung durch con.setAutoCommit(false);
con.commit() ... explizites bestätigen der Transaktion
con.rollback() ... zurückrollen der Transaktion
try{
con.setAutoCommit(false);
//INSERT Anweisungen
con.commit();
} catch(SQLException exc{
con.rollback();
}
Prepared and Callable Statements

Prepared Statement



Vorkompiliert
Reduziert Execution Time
Vorteilhaft, wenn Statement
öfters verwendet wird
PreparedStatement stmt =
con.preparedStatement
(“SELECT plz FROM
Orte”);
ResultSet result=
stmt.executeQuery();

Callable Statement

Enthält Aufruf zu Stored
Procedure
CallableStatement
stmt =
con.prepareCall
(“{call
SP_KUNDEN}”);
ResultSet result=
stmt.executeQuery(
);
SQLJ





Embedded SQL für Java
Wurde von verschiedenen DB-Herstellern
standardisiert
Kein API wie JDBC, sondern
Spracherweiterung
SQLJ Implementierungen basieren allerdings
auf JDBC
Übersichtlicher als JDBC, aber auch weniger
flexibel da statische Einbettung
SQLJ vs. JDBC: INSERT Statement
// SQLJ
// JDBC
int n;
int n;
#sql {INSERT INTO Gehalt
VALUES(:n)};
Statement stmt =
conn.prepareStatement(“INS
ERT INTO Gehalt
VALUES(?)”);
stmt.setInt(1,n);
stmt.execute();
stmt.close();
Abbildung einer Vererbungshierarchie
auf das relationale Modell
Abbildung einer Vererbungshierarchie
auf das relationale Modell (Forts.)
1. Eigene Tabelle für jede Subklasse und für die
Basisklasse
•
•
Allerdings nur Spalten für die Felder, die in der Subklasse
hinzukommen
Wieso ist diese Variante ineffizient?
Viele Joins nötig, um eine Instanz zu erstellen (z.B. 4
Vererbungen  4 Joins)
2. Eigene Tabelle für jede Subklasse
•
•
Tabellen der Subklasse enthalten auch sämtliche Spalten
der Basisklasse
Wann kann man sich die erste Tabelle sparen?
Wenn die Basisklasse abstrakt ist.
Abbildung einer Vererbungshierarchie
auf das relationale Modell (Forts.)
3.Alle Klassen (Basisklasse + Subklassen)
in eine Tabelle
•
•
•
aufgeblähte Tabelle mit vielen Null-Werten
Diskriminator-Attribut, damit man die
Klasse unterscheiden kann
Unterscheidung nur aufgrund der NullWerte ist problematisch
O/R Mapping mit Hibernate
Quellen




Hibernate Docu: www.hibernate.org
Hibernate und die Java Persistence API
(Robert Hien und Markus Kehle,
entwickler.press, 2007)
Hibernate in Action (Christian Bauer
und Gavin King, Manning 2004)
Studienbrief DBPR2
Was ist Hibernate?




weit-verbreiteter O/R Mapper
(www.hibernate.org)
unterstützt eine Vielzahl von DB, inklusive
Oracle, MS SQL Server, IBM DB2,
PostgreSQL, MySQL
open source
Versionen für Java und .NET (NHibernate)
verfügbar
Lebenszyklus einer Hibernate-Entity
Zustände einer Hibernate-Entity

Transient






Jedes Entity-Objekt, das mit new erzeugt wird, befindet sich
im Zustand transient.
Zustand der Entity wird nicht persistent gespeichert
Entity verhält sich wie normales Objekt
Keine Repräsentation in der DB
Daten gehen verloren, sobald es der Garbage Collector
vernichtet
Entities sind im Zustand transient nicht Teil einer
Transaktion, d.h. es gibt auch kein Rollback
Zustände einer Hibernate-Entity

Persistent





Sobald eine Entity einer Session zugeordnet ist
Noch nicht notwendigerweise in der DB repräsentiert, da
Hibernate nicht sofort nach jedem save() runterspeichert.
Alle Entities in diesem Zustand sind Teil einer Transaktion
Änderung von Attributen einer persistenten Entity wird von
Hibernate erkannt und UPDATE in der DB durchgeführt.
Durch session.delete() werden die Daten der Entity aus der
DB gelöscht.
Zustände einer Hibernate-Entity

Detached

Sobald eine Session mit session.close()
geschlossen wird, werden Änderungen mit
der DB nicht mehr synchronisiert.
Die wichtigsten Methoden

session.save():
session.load():

session.refresh():

session.flush():

session.update():

session.delete():

Persistierung transienter Objekte
Erneutes Laden von Objekten, Klasse und
Primärschlüssel nötig
Erneutes Laden aller in der Session
befindlichen Objekte, z.B. nötig wenn sich
Attribute durch Trigger geändert haben
Persistiert alle Änderungen von Objekten, die
sich in der Session befinden
Erneutes Anbinden eines „detached“ Objektes
an eine neue Session
Löschen eines persistenten Objektes. Wird
aus DB und Session entfernt, kann aber
natürlich in der Anwendung weiter existieren.
Mapping in Hibernate
Metadata Annotation des Quellcodes
1.
•
Z.B. mit Java Annotations oder XDoclet Markup
Explizit mit einer Mapping-Datei (xml)
2.
•
•
•
Enthält Infos über Verknüpfung von Objekten mit Tabellen
Tools helfen bei der Erstellung des Grundgerüsts
Erlaubt Hibernate SQL Schemata und Quellcode zu
generieren
Nur Spezifikation des Quellcodes
3.
•
•
Hibernate versucht mit Java Reflection und Heuristiken ein
passendes Mapping zu erstellen
Für einfache Mappings und zur Erstellung des MappingGrundgerüsts
Beispiel Annotation
@Entity(access=AccessType.FIELD)
public class Customer implements Serializable {
@Id;
//kundennummer ist der Primärschlüssel von
Customer
Long kundennummer;
String firstName;
...
@Transient
Integer age;
...
}
//age soll nicht persistiert werden
Bsp. Mapping in XML File
Teil der Mapping-Datei
Klasse Cat wird auf Tabelle
cats gemappt.
id ist Primärschlüssel
birthdate wird persistiert
Datentype date
not null
darf nicht upgedated
werden
Mapping-Datei Fortsetzung
Unidirektionale
Assoziationsabbildung
Unidirektionale
Assoziationsabbildung
Unterschied zu vorher: unique Parameter
Unidirektionale Assoziationsabbildung
33
Unidirektionale Assoziationsabbildung
Bidirektionale Beziehungen
Wie kann man ein Objekt aus der DB
instanzieren?



Session.load()
Dazu muss man den Primary Key kennen
Was macht man, wenn man ihn nicht kennt?
 Query Language
Query Languages von Hibernate
1. Hibernate Query Language (HQL)






Syntaktisch ähnlich zu SQL
Aber voll objekt-orientiert, d.h. Java-Klassen
können in der Abfrage verwendet werden
Objekte werden als Ergebnis geliefert
Bsp.: select c from eg.Cat as c where c.sex=„F‟
Was liefert „from java.lang.object o“
Liefert alle persistenten Objekte aus der DB (da
alles von Object abgeleitet wird)
2. Native SQL
Query Languages von Hibernate
3. Criteria Queries
•
Zusammenbauen einer Abfrage
•
Einzelne Bedingungen, Joins, Sortierungen werden durch Aufruf
von Methoden zum Criteria Object hinzugefügt.
Was macht dieses Statement?
Selektiert alle Katzen, deren Name mit F beginnt und sortiert
sie aufsteigend nach Name und absteigend nach dem Alter. Die
maximale Anzahl an Datensätzen wird auf 50 beschränkt.
Herunterladen