45
Persistenz Muster Muster rund um den Datenbank Zugrif

Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Persistenz Muster

Muster rund um den Datenbank Zugrif

Page 2: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Einleitung Persistenz Muster beschreiben verschiedene

Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von Objekten.o Sie zeigen, wie der Datenzugrif von der

Business-Logik getrennt werden kann.o Sie behandeln Lösungen zu Konflikten beim

Schreiben.o Sie zeigen Lösungen zum Beschleunigen des

Daten-Zugrifs.o Sie behandeln Lösungen zum Vermindern der

Anzahl Zugrife auf die DB.

Beispiele: DAO, Lazy Load, Optimistic Locking, …

Page 3: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

DAO Pattern

Data Access Object

Page 4: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Szenario/Problem/Kontext Die meisten Anwendungen benötigen persistente

Daten, d.h. Daten, welche nach Beenden der Applikation erhalten bleiben.

Bei Änderung der Persistenz-Schicht soll die Applikation möglichst unverändert bleiben.

Es gibt Anwendungen, welche auf Daten zugreifen müssen welche sich auf verschiedenen Systemen befinden.

Gewisse Daten werden durch externe Systeme zur Verfügung gestellt: Business-to-Business Integration-Systeme, Kreditkarte Büro-Services, …

Page 5: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Anwendung/Vorteil Ein Data Access Object (DAO) dient als

Verbindung zwischen der Applikation und der Datenquelle

Das DAO dient dazu, alle Zugrife auf die Datenquelle zu abstrahieren und zu kapseln

Die Datenquelle kann beliebig sein: eine relationale Datenbank, ein externer Dienstleister, ein Repository, ein Business-Service,…

Page 6: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Das DAO Objekt

Data Access Objekt als Verbindungsstelle zwischen den Business Objekten und der Data Source (Datenbank)

Page 7: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Das DAO Objekt Business Objekte (Fachklassen) benötigen Zugrif

auf die Datenbank (Data Source). Das DAO Objekt bietet diesen Zugrif als Dienst

(Methode) an. Für den Datenaustausch dient ein Transfer Objekt

(oder ein Fachklassen-Objekt)

Page 8: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Lösung/Implementation

Lesen

Schreiben

Quelle: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

Page 9: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Lösung/Implementation

Das BusinessObject repräsentiert die Client Daten (Fachklassen). Es benötigt die Daten-Quelle um (indirekt) Informationen zu lesen und zu speichern.

Das DAO abstrahiert den Zugriff auf die Daten-Quelle und enthält Operationen zum Lesen und Schreiben von Daten.

DataSource repräsentiert den Daten Zugriff. Dies kann eine DB Connection, ein File, ein anderes System, … sein. Das DAO regelt alle technischen Aspekte für die konkrete technische DataSource.

(Generisches) Transfer Objekte dient zum Transportieren von Daten von und zu der Daten-Quelle.

Page 10: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

BeispielStudenten-Daten aus DB lesen (Fachklasse als Transfer Objekt)

Jeder Fachklasse wird ein DAO-Objekt zugeordnet, welches den Datenzugriff für diese Fachklasse kapselt. Das ermöglicht eine direkte Verbindung zwischen Fachklassen-Objekt und DAO-Objekt

Page 11: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Definition Data Source und der Query-Strings

Initialisierung

Page 12: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Lesen und Schreiben der Daten

Page 13: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Die Fach-Klasse Student ist unabhängig von der Datenquelle:

. . . }

Page 14: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Der Client kann mit Hilfe des entsprechenden DAO Objekts einen konkreten Studenten aus der Datenbank lesen:

Page 15: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Verwendung

Das DAO Pattern wird sinnvollerweise angewandt wenn

eine Entkoppelung zwischen Fachklassen und Daten-Quelle sinnvoll erscheint saubere Fachklassen durch Wegkapseln der

technischen Aspekte des Datenzugrifs in das DAO

einfaches Testing (Mocking) verschiedene Daten-Quellen vorhanden sind eine einfache Migration der Daten-Quelle

möglich sein soll

Page 16: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Vorteile

Das DAO versteckt die Implementierungs-Details der Persistenz

Transparenter Zugrif

Wenn die zugrunde liegende Datenquelle ihre Implementierung ändert, bleibt die DAO Schnittstelle erhalten, verlangt also von ihren Kunden keinerlei Anpassungen

einfache Migration

DB-Zugrifs-Code (wie z.B. SQL-Anweisungen) ist in das DAO ausgelagert

Verbesserte Lesbarkeit der Business Objekte

Page 17: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Nachteil

Die DAOs legen eine Indirektion zwischen die Business Objekte und die Datenquelle

Mehr Klassen/Objekte nötig

Viele (neue) Beziehungen über Paket-Grenzen

Eventuell müssen Daten umkopiert werden (beim Benutzen von generischen Transfer-Objekten)

(Connection Objekt in allen DAO Objekten → kann durch Verwendung eines Connection Pools umgangen werden)

Page 18: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation mit DAO Factory

Siehe Factory Pattern

. . . }

Page 19: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Die DAOFactory verwaltet die Connection und übergibt sie den DAO Objekten:

Der Client muss das StudentDAO nicht mehr selber instanzieren:

Page 20: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Vorteil / Varianten Entkoppelung der Business-Schicht von den

einzelnen DAO Klassen durch Benutzen einer DAOFactory - sinnvoll, falls es viele DAO-Klassen gibt, z.B.

eine DAO-Klasse für Datenbankzugrif, eine für Filesystemzugrif

Entkoppelung von der DAOFactory durch eine AbstractFactory, falls verschiedene Datenbanken unterstützt werden sollen. Erzeugungsmuster

Page 21: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Praxisbeispiel: Spring Data JPA, Repository-Pattern

Page 22: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Die Fachklasse@Entitypublic class Customer {

@Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; private String firstName; private String lastName;

protected Customer() {}

public Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }

public Long getId() {return id;

}

public String getFirstName() {return firstName;

}

public String getLastName() {return lastName;

}}

Page 23: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Das Repository

public interface CustomerRepository extends CrudRepository<Customer, Long> {

List<Customer> findByLastName(String lastName);}

Page 24: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Der Client@SpringBootApplicationpublic class Application {

private static final Logger log = LoggerFactory.getLogger(Application.class);

public static void main(String[] args) {SpringApplication.run(Application.class);

}

@Beanpublic CommandLineRunner demo(CustomerRepository repository) {

return (args) -> {// save a couple of customersrepository.save(new Customer("Jack", "Bauer"));repository.save(new Customer("Chloe", "O'Brian"));

// fetch all customerslog.info("Customers found with findAll():");log.info("-------------------------------");for (Customer customer : repository.findAll()) {

log.info(customer.toString());}log.info("");

// fetch customers by last namelog.info("Customer found with findByLastName('Bauer'):");log.info("--------------------------------------------");for (Customer bauer : repository.findByLastName("Bauer")) {

log.info(bauer.toString());}log.info("");

};}

}

Page 25: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Verweis auf andere Muster

Verwandte Muster sind Transfer Object/Value Objekt

Ein DAO verwendet Transfer Objekte, um Daten von und zu den Business Objekten zu transportieren. Entkoppelung von der Daten-Schicht.

Factory Method/Abstract FactoryUm die Business Objekte von ihren DAOs zu entkoppeln können Factory-Methoden angewandt werden.Falls zusätzliche Flexibilität zur Erzeugung der DAOs nötig ist, kann das Abstract Factory-Muster eingesetzt werden Entkoppelung von der konkreten DB Implementation

Page 26: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Lazy Loading

Verzögertes Laden

Page 27: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Szenario/Problem/Kontext Innerhalb der Anwendung müssen umfangreiche

Objekte aus der Datenbank bereitgestellt werden.

Die Datenbeschafung kostet viel Zeit, da die Objekte sehr gross sind oder die Informationen in verschiedene DB Tabellen verteilt sind.

Für die Datenbeschafung sind viele DB Zugrife nötig.

Der Client benötigt für den nächsten Schritt (die nächsten Schritte) nur einen (kleinen) Teil der Inhalte.

Page 28: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Szenario/Problem/Kontext Beispiel: Cargo Cruise

Die Details einer Buchung, einer Reise, eines Schifes, … werden erst dann benötigt, wenn der Kundenberater auf die Detail-Ansicht klickt (also ev. gar nicht).

Grundsätzliche Frage: Wie viele Daten sollen sinnvollerweise für den nächsten Arbeitsschritt aus der DB geholt werden?

Optimierung von Zeit und Memory

Page 29: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Lösung

Initialisierung

Nachladen von Daten

Page 30: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

public class Person{ private int id; private String name; private Address homeAddress;

public Person(int id) { // minimal init this.id = id; }

Page 31: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementationpublic String Name{

get{ //Nachladen falls nötig

if (name == null)name = DataSource.getPersonName(id);

return name; }}

public Address HomeAddress{

get{ //Nachladen falls nötig

if (homeAddress == null) homeAddress = new Address( DataSource.getStreet(id), DataSource.getCity(id));

return homeAddress; }}

Page 32: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Praxisbeispiel: Java Persistence API

Page 33: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Vorteile Vom Objekt werden nur diejenigen Daten

geladen, welche zu Beginn benötigt werden. Der DB-Zugrif ist einfach und schnell (kurze

Ladezeit). Im Memory liegen nur benötigte Daten.

Nachteile Durch das Nachladen sind mehr DB Zugrife nötig

und benötigen zusätzliche Zeit. Code wird komplexer.

Page 34: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Verweis auf andere Muster Lazy Initialisierung: Minimale Initialisierung,

Nachladen bei jedem get-Zugrif, der auf null verweist.

Ghost: Das Objekt ist anfangs leer, beim ersten Datenzugrif (get) wird ein vordefinierter Teil nachgeladen. Weiteres Nachladen sobald nötig.

Virtual Proxy: Ein Stellvertreterobjekt ist für das Nachladen der Daten zuständig.

Page 35: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Optimisic Lock

Optimistisches Sperren

Page 36: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Szenario/Problem/Kontext Innerhalb der Anwendung müssen viele Objekte

aus der Datenbank gelesen werden.

Viele Mitbenutzer wollen gleichzeitig (im gleichen Daten-Bereich) von der DB Daten benutzen.

Der Client benötigt für den nächsten Schritt viele Informationen, nur wenig wird verändert und später wieder in die Datenbank geschrieben.

Ein normales (pessimistisches) Lock blockiert grosse Teile der Datenbank und alle anderen Benutzer müssen warten.

Page 37: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Szenario/Problem/Kontext Beispiel: Cargo Cruise

Zu den Informationen einer Buchung gehören auch eher «statische» Daten wie die der Reise, des Schifes, der Reederei, des Kunden…

Diese Daten werden selten oder gar nicht verändert und könnten daher gleichzeitig von mehreren Benutzern gelesen werden.

Page 38: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Lösung

Die Datensätze erhalten eine Versionsnummer als zusätzliches Feld.

Alle Lesezugrife werden zugelassen, es gibt keine Sperrung (Lock).

Erst beim Schreibzugrif wird geprüft, ob die Versionsnummer des Datensatzes in der DB noch mit der lokalen Kopie übereinstimmt.

Falls dies der Fall ist, wird der veränderte Datensatz geschrieben und die Versionsnummer erhöht.

Andernfalls wird eine Fehlermeldung (und der neue Datensatz) ausgegeben.

Page 39: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Sequenzdiagramm Beispiel

Quelle: https://martinfowler.com/eaaCatalog/optimisticOfflineLock.html

Page 40: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Implementation

Beispiel : Schreiben des neuen Zustands einer Buchung

update booking set state = ‘reserved’, version = localVersion + 1where id = ‘localId’ and version = localVersion;

Page 41: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Praxisbeispiel: Optimistic Locking bei Java Persistence API

Page 42: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Vorteile Alle Lesezugrife sind uneingeschränkt möglich. Datensätze die nur gelesen wurden müssen nicht

wieder freigegeben werden.

Nachteile Wenn ein update fehlschlägt, muss der Benutzer

ausgehend vom neuen Datensatz seine Eingaben (möglicherweise) nochmals neu eingeben.

Page 43: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Verwendung Durch ein Cache und Merge kann ev. der Fehler

vermieden/gemildert werden.

Das Pattern kann nur eingesetzt werden, wenn Konflikte (sehr) selten sind.

Für die Bereiche, bei denen konkurrierende Schreibbefehle zu erwarten sind, ist pessimistisches Locking zu empfehlen.

Page 44: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Verweis auf andere Muster

Pessimistic Lock Die Datensätze (welche in diesem

Arbeitsschritt möglicherweise verändert werden könnten) werden bereits beim Lesen gegen weiteren Zugrif gesperrt.

Die Datensätze werden erst wieder freigegeben, wenn die Business-Transaktion abgeschlossen ist.

Page 45: Persistenz Muster - BFHamrhein/ADP/Persistenz.pdf · Einleitung Persistenz Muster beschreiben verschiedene Lösungen von Problemen rund um das Speichern und Lesen (Persistieren) von

Vorteile Pessimistic Lock

Es gibt keine Schreib-Konflikte. Jeder gelesene Datensatz kann garantiert geschrieben werden.

Nachteile Pessimistic Lock Gleichzeitiger Zugrif auf gleichen Datensatz ist

blockiert → Wartezeit. Gelesene Datensätze müssen explizit wieder

(korrekt) freigegeben werden.