21
Object Relational Mapping (ORM)

Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Embed Size (px)

Citation preview

Page 1: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Object Relational Mapping

(ORM)

Page 2: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Objektmodell - Datenbankmodell

Page 3: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

ORM

• Pro Datenbanktabelle eine Klasse im Objektmodell (Data Transfer Object; DTO)

• Pro Datensatz in der Tabelle eine Instanz der Klasse

• Eigene Klassen für die Datenbankzugriffe (Data Access Object; DAO)

Page 4: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

ORM

cd_id cd_interpret cd_titel

1 Robbie W. Best of

2 Madonna Greatest …

… … …

Page 5: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Schattendaten

id (Primärschlüssel)lastUpdate (optimistic locking)storedInDb (bereits als Datensatz vorhanden)

Page 6: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Data Access Object (DAO)

• Verschiedene Methoden für das Auswählen

• Speichern

• Löschen

Page 7: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

findByPrimaryKey()SELECT cd_interpret, cd_titel

FROM CDSWHERE cd_id = ?

ResultSet rs = …if (rs.next()){

CD cd = new CD();cd.setId(id);cd.setTitel(rs.getString("cd_titel"));cd.setInterpret(rs.getString("cd_interpret"));return cd;

}else

return null;

Page 8: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

findAll()SELECT cd_id, cd_interpret, cd_titel

FROM CDS

List<CD> liste = new ArrayList<CD>();ResultSet rs = …while (rs.next()){

CD cd = new CD();cd.setId(rs.getInt("cd_id"));cd.setTitel(rs.getString("cd_titel"));cd.setInterpret(rs.getString("cd_interpret"));liste.add(cd);

}…return liste;

Page 9: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

findByTitle()SELECT cd_id, cd_interpret, cd_titel

FROM CDSWHERE cd_titel = ?

List<CD> liste = new ArrayList<CD>();ResultSet rs = …while (rs.next()){

CD cd = new CD();cd.setId(rs.getInt("cd_id"));cd.setTitel(rs.getString("cd_titel"));cd.setInterpret(rs.getString("cd_interpret"));liste.add(cd);

}…return liste;

Page 10: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

save(CD cd)

if (cd.isStoredInDb()){

// UPDATE...

}else{

// INSERT...

}

PreparedStatement pstmt = …

if (pstmt.executeUpdate() == 1){

// ok}else{

// Fehler}

INSERT INTO CDS (cd_id, cd_interpret, cd_titel)VALUES (?, ?, ?)

UPDATE CDS SET cd_interpret = ?, cd_titel = ?WHERE cd_id = ?

Page 11: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

remove()

DELETE FROM CDSWHERE cd_id = ?

PreparedStatement pstmt = …

if (pstmt.executeUpdate() == 1){

// ok}else{

// Fehler}

Page 12: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Einige wichtige Regeln

• Parametrierte (?) Statements verwenden

• Einzelne Spalten mit Namen ansprechen (kein „SELECT * …“)

• Update-Count überprüfen

• Datenbankverbindung wiederverwenden

• ResultSet und PreparedStatement schließen

Page 13: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

INSERT und Primary Key

cd_id cd_interpret cd_titel

1 Robbie W. Best of

2 Madonna Greatest …

… … …INSERT

Page 14: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

ResultSet keys = pstmt.getGeneratedKeys();if (keys.next())

cd.setId(keys.getInt(1));

INSERT und Primary Key

• getGeneratedKeys()

• Sequenzen

Page 15: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

DTO Caching

Beispiel:dao.findByPrimaryKey(key) liefert eine Referenz auf die CD-Instanz mit dem übergebenen Primärschlüssel.

Problem: Bei mehreren Aufrufen mit dem selben key sollte immer die selbe Instanz geliefert werden.

Lösung:DAO muss einen Cache von bereits aus Datenbank ausgelesenen Instanzen halten (z.B Map<Key,DTO>)

Page 16: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Inkonsistenzen bei Fehlerfällen

Beispiel:Überweisung eines Betrages von einem Bankkonto auf ein anderes.Saldo wird beim ersten Konto um den Betrag reduziert. Bevor der Saldo beim zweiten Konto entsprechend erhöht wird, stürzt das Programm ab. Inkonsistenz

Lösung:Verwenden einer Transaktion

Page 17: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Datenbank-Transaktion

In JDBC hängt die Transaktion an der Datenbankverbindung (Connection):•con.setAutoCommit(false);•con.commit(); •con.rollback();Jedes commit() oder rollback() beginnt zugleich die nächste Transaktion.

Savepoints:•Savepoint sp = con.setSavepoint();•con.rollback(sp);

Page 18: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Gleichzeitige Zugriffe

Problem:2 Clients bearbeiten den selben Datensatz.• Beide Clients holen den Datensatz aus der Datenbank• Client 1 ist fertig mit der Bearbeitung und führt ein Update

durch.• Client 2 ist fertig mit der Bearbeitung und führt ein Update

durch. Die Änderungen von Client 1 gehen verloren.

Lösung:Datensatz muss beim Auslesen aus der Datenbank

gesperrt werden. Datenbank-spezifisch: SELECT ... FOR UPDATE; LOCK TABLE ...

Page 19: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Pessimistic Locking

• Datensatz wird ausgelesen und gesperrt.• Datensatz wird bearbeitet.• Update wird durchgeführt.• Datensatz wird freigegeben.

Nachteil:Datensatz sehr lange gesperrt, wenn

Programm abstürzt, etc.

Page 20: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Optimistic locking

• Datensatz wird ausgelesen aber nicht gesperrt.• Datensatz wird bearbeitet.• Datensatz wird noch einmal ausgelesen und

diesmal gesperrt.• Falls Datensatz noch gleich ist wie beim ersten

Auslesen Update und Freigabe• Falls Datensatz inzwischen verändert wurde,

müssen Änderungen verworfen oder zusammengeführt werden.

Page 21: Object Relational Mapping (ORM). Objektmodell - Datenbankmodell

Update-Timestamp

Jede Tabelle erhält ein zusätzliches Timestamp-Feld (last_upd). Darin wird Zeitpunkt des letzten Updates gespeichert.•Datensatz wird ausgelesen•Datensatz wird bearbeitet•Update:

UPDATE … WHERE last_upd = …

Wenn zwischendurch kein Update von anderem Client erfolgt ist, ist Update-Count = 1, ansonsten 0.