Anbindung an relationale Datenbanken

Werbung
Softwaretechnik
Anbindung an relationale Datenbanken
Prof. Dr. Matthias Hölzl
Joschka Rinke
13. Januar 2016
Anbindung an eine Datenbank
Ziel
Speicherung von persistenten Objekten, d.h. von Objekten des
Anwendungskerns, die dauerhaft benötigt werden (z.B. Kunden,
Konten, Flüge, Bücher, . . . ).
Möglichkeiten
I
Relationale Datenbanken: Unterstützen Assoziationen und
Vererbung nicht. Deshalb wird eine explizite Schnittstelle
zwischen dem Anwendungskern und dem relationalen
Datenbanksystem benötigt.
I
Objektrelationale Datenbanken: Erweitern relationale
Datenbanken um objektorientierte Konzepte, meist Vererbung.
I
NoSQL-Datenbanken Sammelbegriff für Datenbanken, die
nicht dem relationalen Modell folgen
Varianten von NoSQL-Datenbanken
I
I
I
I
I
Objektorientierte Datenbanken: Unterstützen Assoziationen,
Vererbung und Operationen. ODMG-Standard: ODL (object
definition language) für Schemadeklarationen, OQL (object
query language) und Sprachanbindungen
Dokumentenorientierte Datenbanken: Enthalten nicht
Tabellen mit vorgegebenem Schema sondern Dokumente, z.B.
im XML oder JSON Format (CouchDB, MongoDB)
Graphdatenbanken: Speichern Graphen, entweder als Knoten
und Kanten, die beide durch Attribute annotiert werden
können, oder als Tripel/Quadrupel (RDF, Abfragesprache
SPARQL)
Key-Value Datenbanken: Verwenden ein einfaches assoziatives
Array als zugrundeliegendes Datenmodell (Berkeley DB,
Apache Dynamo)
Spaltenorientierte Datenbanken: Speichert Tabellen
Spaltenweise, nicht zeilenweise (Cassandra, HBase)
Anbindung an Relationale Datenbanken
Abbildung eines Objektmodells auf Tabellen
Voraussetzung
Für jede Entity-Klasse A ist ein Primärschlüsselattribut aKey
eingeführt.
Abbildung von Klassen
Tabelle A
<<entity>>
A
aKey
a1
...
an
...
aKey
a1
...
an
Abbildung von Assoziationen
Multiplizität * - *
Verwendung einer eigenen Tabelle mit den Primärschlüsseln von A
und B.
A
aKey
...
*
*
B
bKey
...
aKey
bKey
Abbildung von Assoziationen
Multiplizität * - 0..1
Primärschlüssel von B als Fremdschlüssel in die Tabelle von A
aufnehmen.
A
aKey
...
*
0..1
B
bKey
...
aKey
a1
Abbildung von Assoziationen
Multiplizität 0..1 - 0..1
Primärschlüssel von B in die Tabelle von A oder
Primärschlüssel von A in die Tabelle von B aufnehmen.
0..1
A
0..1
aKey
...
B
aKey
a1
...
an
bKey
bm
aKey
bKey
...
oder
bKey
b1
...
Bemerkung
A
0..1
1
B
Bei
ist der Primärschlüssel von B als
Fremdschlüssel zur Tabelle von A hinzuzunehmen.
Abbildung von Vererbung
A
key
a
B
b
C
c
Abbildung von Vererbung
Variante I: Je eine Tabelle pro Klasse
Tabelle A
key
a
Tabelle B
key
b
Tabelle C
key
c
Nachteil:
Bei Anfragen und Manipulationen, die Objekte einer Unterklasse
betreffen, müssen ggf. Einträge in mehreren Tabellen berücksichtigt
werden (z.B. bei Auswahl aller Attributwerte aller B-Objekte).
Abbildung von Vererbung
Variante II: Tabellen von Unterklassen enthalten geerbte
Attribute
Tabelle A
key
a
Tabelle B
key
a
Tabelle C
b
key
a
c
Falls A abstrakt ist, genügt eine Tabelle pro Unterklasse (Tabelle A
entfällt).
Nachteil:
Bei Änderungen an der Form der Oberklasse, müssen auch die
Tabellen der Unterklassen verändert werden.
Abbildung von Vererbung
Variante III: Eine Tabelle für alle Ober- und Unterklassen
Tabelle ABC
key
a
b
c
Typ
Nachteil:
In Spalten, die für Objekte einer Unterklasse nicht relevant sind,
müssen Nullwerte eingetragen werden.
Datenbankanbindung mit JDBC
I
JDBC (Java Database Connectivity) bietet eine
SQL-Schnittstelle für Java-Programme
I
JDBC ist unabhängig von einem konkreten (relationalen)
Datenbanksystem. Zum Zugriff auf ein konkretes
Datenbanksystem muss ein entsprechender Treiber geladen
werden
Schichten einer JDBC-Anwendung
Java−Anwendungskern
<<access>>
JDBC−Datenbankschnittstelle
java.sql::DriverManager
JDBC−Treiber
JDBC−Treiber
DBMS
DBMS
java.sql
JDBC-Kurzüberblick
<<interface>>
Connection
DriverManager
+getConnection(url: String): Connection
+registerDriver(d: Driver)
+getDriver(url: String): Driver
<<interface>>
Statement
+createStatement(): Statement
+executeQuery(sql: String): ResultSet
+close()
...
+executeUpdate(sql: String): Integer
...
+getResultSet(): ResultSet
...
*
<<interface>>
Driver
+connect(url: String, info:Properties): Connection
...
Liefert Daten der Spalte i der
aktuellen Zeile als String−Objekt
<<interface>>
ResultSet
+getString(i: Integer): String
+getInt(i: Integer): Integer
Geht zum ersten bzw. zum
nächsten Datensatz
...
+next(): Boolean
JDBC-Kurzüberblick
I
Driver“, Connection“, Statement“ und ResultSet“ sind
”
”
”
”
Schnittstellen, die von den Klassen eines geladenen
Treiberpakets implementiert werden
I
Der DriverManager registriert Treiber für bestimmte
DB-Systeme. Der Aufruf der statischen Operation
getConnection“ stellt (mittels eines für die gegebene URL
”
passenden Treibers) eine Verbindung zu einem DB-System her
I
Mittels eines Connection-Objekts kann ein Statement-Objekt
erzeugt werden (Operation createStatement“)
”
←-
JDBC-Kurzüberblick
I
I
I
I
Mittels eines Statement-Objekts kann z.B. eine Anfrage an die
DB gestellt werden (Operation executeQuery“)
”
Die Ergebnistabelle der Anfrage wird in einem
ResultSet-Objekt gespeichert
Die Tabelle eines ResultSet-Objekts kann mit der Operation
next“ zeilenweise durchlaufen werden
”
Auf die Felder innerhalb einer Zeile kann mit einer (bzgl. des
Spaltentyps) passenden get-Operation zugegriffen werden
Beispiel:
try {
// Treiber auch von außen setzbar
Class.forName("imaginary.sql.iMsqlDriver");
String url = "jdbc:msql://localhost/myDB";
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();
ResultSet rs
= stmt.executeQuery("SELECT * FROM test");
while (rs.next()) {
// Zugriff auf die Spalte mit der Nummer y und dem Typ XXX
// in der aktuellen Zeile
XXX v = rs.getXXX(y);
}
con.close();
}
catch (Exception e) {
e.printStackTrace();
}
Materialisierung von Objekten
Gegeben
Klassen im Anwendungskern:
A
B
−aKey: String
−bKey: String
−a1: Typ1
...
−b1: Typ1
...
−an: Typn
−bm: Typm
+setAKey(x: String)
+setBKey(x: String)
+setA1(x: Typ1)
...
+setB1(x: Typ1)
...
←-
Materialisierung von Objekten
Gegeben
Tabellen in der relationalen Datenbank:
Tabelle A
aKey
a1
...
Tabelle B
an
bKey
b1
...
bm
Materialisierung mit JDBC
1
RDBBroker
{abstract }
stmt = con.createStatement();
rs = stmt.executeQuery( "SELECT * FROM " + tabname() +
" WHERE " + keyname() + " = " + "’" + key + "’");
if (rs.next()) return recordAsObject();
else return null;
con = c;
return "A";
#con
+ materialize(key: String): Object
# recordAsObject(): Object {abstract}
0..1
−stmt
# tabname(): String {abstract}
0..1
# keyname(): String {abstract}
# rs
ARDBBroker
BRDBBroker
+ ARDBBroker(c: Connection)
+ BRDBBroker(c: Connection)
# recordAsObject(): Object
# recordAsObject(): Object
# tabname(): String
# tabname(): String
# keyname(): String
# keyname(): String
return "aKey";
A a = new A();
a.setKey(rs.getString(0));
a.setA1(rs.getTyp1(1));
...
a.setAn(rs.getTypn(n));
return a;
<<interface>>
Connection
<<interface>>
Statement
<<interface>>
ResultSet
Materialisierung mit JDBC
try {
String url = "jdbc:RDB-Typ//Rechner:Port/Datenbank";
Connection con = DriverManager.getConnection(url);
ARDBBroker ardb = new ARDBBroker(con);
BRDBBroker brdb = new BRDBBroker(con);
A a = (A)ardb.materialize("xyz");
B b = (B)brdb.materialize("uvw");
}
catch (Exception e) {
e.printStackTrace();
}
Materialisierung mit JDBC
Bemerkungen
I
Zur Verbesserung der Effizienz werden häufig
Zwischenspeicher (Cache) verwendet.
I
Bei der Materialisierung von Objektstrukturen werden häufig
nur die gerade benötigten Objekte geladen (on-demand
materialization).
I
Persistenz-Frameworks enthalten noch weitere Mechanismen
z.B. zur Dematerialisierung und zur Transaktionskontrolle.
Zusammenfassung
I
Zur Speicherung persistenter Objekte muss der
Anwendungskern an eine Datenbank angeschlossen werden.
I
Dazu können relationale, objektrelationale oder NoSQL
Datenbanken verwendet werden.
I
Bei der Verwendung einer relationalen Datenbank muss
zunächst das Objektmodell auf Tabellen abgebildet werden.
(Insbesondere müssen Vererbungshierarchien geeignet
abgebildet werden!)
I
JDBC bietet eine plattformunabhängige Schnittstelle zur
Anbindung von Java-Programmen an relationale Datenbanken.
I
Für das Object-Relational-Mapping“ (ORM) verwendet man
”
meist Persistenz-Frameworks.
Herunterladen