Object Relational Mapping Layer GUI OO-application

Werbung
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Object Relational Mapping Layer
Views
Controlers
Business logic
GUI
OO-application logic
Object-relational-Mapping
Relational DBMS
Andreas Schmidt
PHP (Teil 3) 1/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
object relational mapping layer
• two concepts:
• descriptive query language SQL (set oriented)
• imperative programming language (tuple oriented)
• solution: build a mapping layer between the database and the application layer
• which functionality should the mapping layer provides ?
• mapping of PHP objects and their relations to database tables
• encapsulation of SQL statements
• decoupling of the application logic from the database design
• which functionality should the mapping layer not provides ?
• application logic
Andreas Schmidt
PHP (Teil 3)
2/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
object relational mapping layer
• observation: a number of operations can be derived out of the ER-Diagram (or UML-Diagram):
• creation/deletion of objects
• modification of objects
• modification of relations between objects
• search for objects
• this functionality is also known as CRUD-funktionality
(Create, Read, Update, Delete)
Andreas Schmidt
PHP (Teil 3)
3/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
CRUD Interface - necessary methods
plays_role
id
<0,n>
id
<0,n>
Person
Film
<0,1>
title
Andreas Schmidt
year
birthday
<0,n>
directs
firstname
surname
PHP (Teil 3)
4/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Tabellenstruktur
CREATE TABLE person (
id INT (10) AUTO_INCREMENT,
name VARCHAR (40) NOT NULL,
vorname VARCHAR(40) NOT NULL,
geburtsjahr YEAR(4),
PRIMARY KEY(id)
) TYPE=InnoDB;
CREATE TABLE film (
id INT (10) AUTO_INCREMENT,
titel VARCHAR (100) NOT NULL,
jahr year(4),
regisseur_fk INT (10),
FOREIGN KEY (regisseur_fk) REFERENCES person(id)
ON DELETE SET NULL,
PRIMARY KEY(id)
) TYPE=InnoDB;
CREATE TABLE hat_rolle (
schauspieler_fk INT(10) NOT NULL,
film_fk INT(10) not null,
FOREIGN KEY(film_fk) REFERENCES film(id) ON DELETE CASCADE,
FOREIGN KEY(schauspieler_fk) REFERENCES person(id)
ON DELETE CASCADE
) TYPE=InnoDB;
Andreas Schmidt
PHP (Teil 3)
5/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Klassenstruktur in PHP (Variante 1)
class CRUD_Film {
private
private
private
private
private
class CRUD_Person {
$id;
$title;
$year;
$regisseur;
$actors = array();
private
private
private
private
private
private
function __construct(...) {
function __construct(...) {
}
}
// ...
// ...
}
Andreas Schmidt
$id;
$firstname;
$surname;
$birthdate;
$directed_films = array();
$films = array();
}
PHP (Teil 3)
6/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Klassenstruktur in PHP (Variante 2)
class CRUD_Film {
private
private
private
private
class CRUD_Person {
$id;
$title;
$year;
$regisseur_fk;
private
private
private
private
function __construct(...) {
function __construct(...) {
}
}
// ...
// ...
}
Andreas Schmidt
$id;
$firstname;
$surname;
$birthdate;
}
PHP (Teil 3)
7/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
CRUD Interface - necessary methods
(Class CRUD_Person)
• static methods:
• instance methods:
$p->delete()
$p = CRUD_Person::create($name, ...)
$p = CRUD_Person::get($id)
$p_list = CRUD_Person::query($cond)
// Accessor/Mutatormethoden:
$p->getFirstname(), $f->setFirstname($n)
$p->getSurname(), $p->setSurname($n)
$p->getBirthday(), $p->setBirthday($d)
$p->getFilms()
$p->getDirectedFilms()
// Modification of Relationships
$p->addFilm($film)
$p->deleteFilm($film)
$p->addDirectedFilm($film)
$p->delDirectedFilm($film)
Andreas Schmidt
PHP (Teil 3)
8/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
CRUD Interface - necessary methods
(Class CRUD_Film)
• static methods:
• instance methods:
$f->delete()
$f = CRUD_Film::create($title, $year)
$f = CRUD_Film::get($id)
// Accessor/Mutatormethoden:
f->getTitle(), $f->setTitle($t)
$f->getYear(), $f->setYear($y)
$f_list = CRUD_Film::query($cond)
$f->getRegisseur()
$f->getActors()
// Modification of Relationships
$f->addActor($actor)
$f->deleteActor($actor)
$f->setRegisseur($r)
$f->unsetRegisseur()
Andreas Schmidt
PHP (Teil 3)
9/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
CRUD interface (1)
relation between methods and SQL-statements
method
SQL-statement
Parameter
CRUD_Film::create($title,
$year)
INSERT
VALUES
INSERT
VALUES
$title,
$year
CRUD_Film::get($id)
SELECT id, title, year, regisseur_fk
FROM Film
WHERE id = ?
$id
CRUD_Film::query($cond)
SELECT id, title, year, regisseur_fk
FROM Film
WHERE $cond
$cond
$f->delete()
DELETE
FROM Film
WHERE id = ?
$this->id
$f->setTitle($title)
UPDATE Film
SET title = ?
WHERE ID = ?
$title
$this->id
Andreas Schmidt
INTO Film (title, year)
-- mysql
(?, ?)
INTO Film (title, year, id) -- oracle
(?, ?, seq.nextval)
PHP (Teil 3) 10/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
CRUD interface (2)
method
SQL-statement
SQL-parameter
$f->addActor($actor)
INSERT INTO plays_role (actor_fk, film_fk)
VALUES (? , ?)
$actor->getId(),
$this->id
$f->deleteActor($actor)
DELETE from plays_role
WHERE actor_fk = ?
AND film_fk = ?
$actor->getId(),
$this->id
$f->getActors()
SELECT
FROM
WHERE
AND
$this->id
$f->setRegisseur($person)
UPDATE Film
SET regisseur_fk = ?
WHERE ID = ?
$person->getId(),
$this->id
$f->getRegisseur()
SELECT surname, prename, id, birthday
FROM Person
WHERE id = ?
$this->regisseur_fk
Andreas Schmidt
prename, surname, id, birthday
Person, plays_role
plays_role.film_fk = ?
plays_role.actor_fk=Person.id
PHP (Teil 3)
11/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
example implementation (getActors())
class CRUD_Film {
// other methods in this class ...
function getActors() {
$db = PDO_Util::getConnection();
$sql = "SELECT id, prename, surname, birthday
FROM Person, plays_role
WHERE plays_role.actor_fk=Person.id
AND plays_role.film_fk = ?";
$stmt = $db->prepare( $sql );
$stmt->execute(array($this->id));
$list = array();
while($row = $stmt->fetch())
$list[] = new CRUD_Person($row[0], $row[1], $row[2], $row[3]);
return $list;
}
} // end class Film
Andreas Schmidt
PHP (Teil 3) 12/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
First Level Cache
• Werden Änderungen an den Objekten nicht sofort in die Datenbank geschrieben kann es
sein, dass mehrere Kopien desselben Objektes im Speicher existieren, die einen unterschiedlichen Status haben
• Ausweg: Cache
• Prinzip:
• jedes Objekt, das aus Datenbank gelesen wird, wird in Cache eingetragen
• beim Zugriff auf DB wird geschaut ob sich Objekt nicht bereits in Cache befindet,
wenn ja dann wird das Objekt zurückgeliefert (zusätzlich Performancegewinn !!)
• bei Commit werden die geänderten Objekte des Caches zurückgeschrieben
• Implementierung:
• z.B. mit assoziativem Array (Dictionary), wobei der Schlüssel durch Objekt-ID repräsentiert wird und der Wert durch das Objekt selbst (Reference auf Objekt)
Andreas Schmidt
PHP (Teil 3) 13/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
First Level Cache
$obj1
$stadt3
$hauptstadt
Cache
Andreas Schmidt
PHP (Teil 3)
14/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Second level cache
• Bereits angefrage Datensätze verbleiben im Cache und werden bei späteren
Anfragen von dort geladen
• Geeignet für folgende Typen von Daten:
• geringe Änderungsrate
• unkritische Daten (non financial)
• Anwendungslokale (non shared) Daten
• Reference data
• geringe Anzahl von Instanzen
• jede Instanz ist mit vielen Instanzen anderer Klassen verbunden
• seltener Update
Andreas Schmidt
PHP (Teil 3) 15/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Synchronisation
• Szenario:
• User 1 liest Datensatz und modifiziert ihn in einer Bildschirmmaske
• User 2 liest anschließend denselben Datensatz und modifiziert ihn ebenfalls
•
•
User 1 speichert den geänderten Datensatz zurück
User 2 speichert ebenfalls den von ihm geänderten Datensatz zurück
• Problem:
• Änderungen von User 1 sind verloren gegangen
Andreas Schmidt
PHP (Teil 3) 16/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Lösungsansätze
• Pessimistische Synchronistaion
• zu bearbeitender Datensatz wird während der Dauer der Bearbeitung gesperrt
(Sperrattribut, Tabelle(n) zur Sperrenverwaltung)
• Optimistische Synchronisation
• man geht von keiner „Kollision“ aus
• tritt Kollision auf, so muss diese von der Anwendung/dem Anwender gelöst werden
• Prinzip:
• Datensatz erhält zusätzliches Attribut mit Zeitstempel oder Versionsnummer
• Bei jeder Modifikation wird Zeitstempel neu gesetzt, bzw. Versionsnummer
hochgezählt
• Beim Abspeichern wird der aktuelle Wert des Zeitstempels bzw. der Versionsnummer mit verglichen
Andreas Schmidt
PHP (Teil 3) 17/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
DDL (optimistische Synchronisation)
create table Person (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
geburtsdatum date,
version integer not null
);
Andreas Schmidt
PHP (Teil 3) 18/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Beispiel
bei Update
versionsnummer hochzählen
function update() {
$db = PDO_Util::getConnection();
$sql = "update person set name=?, vorname=?, version=version+1
where id=? and version= ?";
$values = array($this->name, $this->vorname, $this->id, $this->version);
$stmt = $db->prepare( $sql );
$stmt->execute( $values );
$affected_rows = $stmt->rowCount();
if ($affected_rows != 1)
return false;
else {
$this->version++;
return true;
}
test ob Datensatz
zurückgeschrieben wurde
}
update des Zählers in der Instanz
Andreas Schmidt
PHP (Teil 3) 19/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Vererbung
vorname
Person
name
eintrittsdatum
isa
Angestellte
Kunde
bonusmeilen
sicherheitsstufe
Andreas Schmidt
Bodenpersonal
isa
flugstunden
Pilot
PHP (Teil 3) 20/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
relationale Modellierung
• 1 Tabelle pro Klassenhierarchie
• 1 Tabelle pro Klasse
• 1 Tabelle pro Verebungspfad
Andreas Schmidt
PHP (Teil 3) 21/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Eine Tabelle pro Klassenhierarchie
Person
Kunde
Angestellter
Bodenpersonal
Pilot
Person
id typ name
vorname bonusmeilen eintrittsdatum sicherheitsstufe flugstunden
001
002
003
004
Vielflieg 600.000
Albatros NULL
Sicher
NULL
Flugangst 10
K...
P...
B...
K...
Andreas Schmidt
Sven
Maria
Sigi
Andrea
NULL
9.9.1980
1.8.1995
NULL
NULL
NULL
E
NULL
NULL
20.000
NULL
NULL
PHP (Teil 3) 22/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
zugeh. DDL/DML-Statements
create table Person (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
bonusmeilen integer,
eintrittsdatum date,
sicherheitsstufe integer,
flugstunden integer,
typ enum ('Kunde', 'Bodenpersonal', 'Pilot')
);
insert into person (id, typ, vorname, name, bonusmeilen)
values(1,'Kunde','Sven','Vielflieg',600000);
insert into person (id, typ, vorname, name, eintrittsdatum, flugstunden)
values(2,'Pilot','Maria','Albatros', '1980-9-9', 20000);
Andreas Schmidt
PHP (Teil 3) 23/33
Fakultät IWI
DB & IS II - WS 2016
Eine Tabelle pro Klasse
Person
Kunde
Angestellter
Bodenpersonal
Pilot
Person
id
typ
001
Kunde
Sven
Vielflieg
002
Pilot
Maria
Albatros
003
Bodenpersonal Sigi
004
Kunde
Kunde
id_fk
vorname
name
Sicher
Andrea
Flugangst
Angestellter
bonusmeilen
id_fk
eintrittsdatum
001
600.000
002
9.9.1980
004
12
003
1.8.1995
Bodenpersonal
id_fk sicherheitsstufe
003
Andreas Schmidt
E
Pilot
id_fk
002
flugstunden
20.000
PHP (Teil 3)
24/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
zugeh. DDL-Statements
create table Person (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
typ enum ('Kunde',
'Bodenpersonal',
'Pilot')
);
create table Kunde (
id_fk integer primary key,
bonusmeilen integer,
foreign key(id_fk) references
Person(id) on delete cascade
);
Andreas Schmidt
create table Angestellter (
id_fk integer primary key,
eintrittsdatum date,
foreign key(id_fk) references
Person(id) on delete cascade
);
create table Bodenpersonal (
id_fk integer primary key,
sicherheitsstufe integer,
foreign key(id_fk) references
Angestellter(id_fk) on delete cascade
);
create table Pilot (
id_fk integer primary key,
flugstunden integer,
foreign key(id_fk) references
Angestellter(id_fk) on delete cascade
);
PHP (Teil 3) 25/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
zugeh. DML-Statements
insert into person (id, vorname, name, typ)
values(1,'Sven','Vielflieg','Kunde');
insert into kunde (id_fk, bonusmeilen)
values(1, 600000);
insert into person (id, vorname, name, typ)
values(2,'Maria','Albatros','Pilot');
insert into angestellter (id_fk, eintrittsdatum)
values (2,'1980-9-9');
insert into pilot (id_fk, flugstunden)
values (2,20000);
Andreas Schmidt
PHP (Teil 3) 26/33
Fakultät IWI
DB & IS II - WS 2016
Eine Tabelle pro Vererbungspfad
Person
Kunde
Angestellter
Bodenpersonal
Pilot
Kunde
id
name
vorname
bonusmeilen
001 Sven
Vielflieg
600.000
004 Andrea
Flugangst
12
Bodenpersonal
id
name
003 Sigi
vorname
Sicher
eintrittsdatum
1.8.1995
sicherheitsstufe
E
Pilot
id
002
name
Maria
Andreas Schmidt
vorname
Albatros
eintrittsdatum
9.9.1980
flugstunden
20.000
PHP (Teil 3)
27/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
zugeh. DDL/DML-Statements
create table Kunde (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
bonusmeilen integer
);
create table Bodenpersonal (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
eintrittsdatum date,
sicherheitsstufe integer
);
insert into kunde (id, vorname, name,
bonusmeilen)
values(1,'Sven','Vielflieg',600000);
insert into pilot (id, vorname, name,
eintrittsdatum, flugstunden)
values(2,'Maria','Albatros','1980-9-9',20000);
create table Pilot (
id integer primary key,
name varchar(40) not null,
vorname varchar(40) not null,
eintrittsdatum date,
flugstunden integer
);
Andreas Schmidt
PHP (Teil 3) 28/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Methoden
• Statische Methoden:
• Instanzenmethoden
$pe
$ku
$bo
$pi
$p->getType() // liefert Typname zurück
=
=
=
=
Person::create($name, $vorname)
Kunde::create(..., $bonusmeilen)
Bodenpersonal::create(...)
Pilot::create(...)
$p->hasType($type)
$px = Person::get(...)
//
//
//
//
true, falls der Typ von p
dem von $type oder einem
davon abgeleiteten
entspricht
$p->delete()
$personen = Person::query($cond)
$piloten = Pilot::query($cond)
// Accessor + Mutatormethoden
...
// Beziehungsmethoden
...
Andreas Schmidt
PHP (Teil 3) 29/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
Performanceüberlegungen
•
•
•
•
•
•
•
„Instant loading“ vs. „lazy loading“
„lazy object generation“ (proxy objects)
„late execution“ von SQL-Update Statements
Cache mit prepared-statements (z.B. Dictionary mit SQL-Statements als Key)
Cache für Ergebnisse bei Beziehungen (Variante 2)
Outer Join bei <0,1> Kardinalität
Update nur auf geänderte Spalten
Andreas Schmidt
PHP (Teil 3) 30/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
application logic
Views
Controlers
Business logic
GUI
OO-application logic
Object-relational-Mapping
Relational DBMS
Andreas Schmidt
PHP (Teil 3) 31/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
application logic
•
•
•
•
•
Applikationslogik wird in Schicht oberhalb der OR-Mapping Schicht realisiert
Applikationslogik ist unabhängig von darunterliegender Datenbankschicht
Frage: wie wird Applikationslogik ins System integriert ?
Antwort: z.B. durch Unterklassenbildung (ableiten derCRUD-Klassen)
Prinzip:
class Film extends CRUD_Film {
private ...
function __construct(...) {
parent::__construct(...);
...
}
// Methods of class Film
// ...
• Notwendige Änderungen an OR-Schicht: OR-Schicht darf nur Instanzen der
abgeleiteten Klassen erzeugen
Andreas Schmidt
PHP (Teil 3) 32/33
Fakultät für Informatik & Wirtschaftsinformatik
DB & IS II - WS 2016
application logic
class Film extends CRUD_Film {
// Realisierung der Applikationslogik unter Zuhilfenahme der Funktionalität
// der durch die OR-Schicht bereitgestellte Funktionalität
// ...
function numberOfActors() {
return count($this->getActors());
}
// weitere Methoden ...
}
Hinweis: Aus Performancegründen ist hier eventuell doch die Ausführung eines
SQL-Statements sinnvoll !!
Andreas Schmidt
PHP (Teil 3) 33/33
Herunterladen