Open Source im professionellen Einsatz

Digitale Bilder mit Perl archivieren und verwalten - Teil 2

Foto-Finish

Der zweite und abschließende Teil über das digitale Bildarchiv beschreibt die zum Frontend aus dem ersten Teil passende Datenbankschnittstelle. Sie benutzt die neue Perl-Wunderdroge Class::DBI.

Das Fotoarchiv-Frontend aus dem letzten Perl-Snapshot[1] archiviert digitale Fotos in speziellen Verzeichnissen auf der Festplatte und pflegt eine Datenbank mit Informationen zu den Bildern. Das Frontend benutzt dazu ein ebenfalls in Perl geschriebenes Backend, das auf die relationale Datenbank zugreift.

Für diesen Zugriff kommt das Perl-Modul Class::DBI zum Einsatz - es legt eine Objektschicht um traditionelle relationale Datenbanken. Der Programmierer navigiert damit auf Applikationsebene unbeschwert zwischen Objekten, während unten im Motorraum die SQL-Befehle hin und her flitzen. Dabei gibt sich Class::DBI offen für neue Ideen. Für den Fall, dass optimiertes SQL doch effizienter läuft als das vorgegebene Objekt-Mapping, bietet es eine Schnittstelle an, über die man problemlos SQL-Code injizieren kann.

Das Fotoarchiv-Frontend »idb« vom letzten Monat nutzt das im Folgenden vorgestellte Perl-Modul »CameraStore.pm«, um die Daten der digitalen Fotos und ihre Beschriftungen in die Datenbank zu verlagern und von dort wieder abzuholen. Es benutzt dazu die in Tabelle 1 genannten Methoden.

Tabelle 1: »CameraStore«-Methoden

Tabelle 1: »CameraStore«-Methoden

Im Motorraum

Zwischen Bildern und Tags besteht eine n:n-Beziehung: Einem Bild können mehrere Tags anhaften, ein Tag kann zu mehreren Bildern gehören. Das erfordert datenbanktechnisch einen Klimmzug. Gäbe es nur je eine Tabelle für Bilder und Tags, müsste die Datenbank bei jedem Tag die zugehörigen langen Bild-IDs speichern und zusätzlich bei jedem Bild die passenden Tag-Strings ablegen. Diese Redundanz verschwendet nicht nur Speicherplatz, sie führt auch zu Wartungsproblemen.

Die bessere Lösung benutzt eine Vermittlertabelle »tags«, die zwischen der Bildtabelle »images« und der Tag-String-Tabelle »categories« steht (Abbildung 1). Jede einzelne Reihe in »tags« gibt an, dass dem in der Spalte »image« eingetragenen Bild das in »category« referenzierte Tag zugeordnet ist.

Die Spalten »image« und »category« der Tabelle »tags« enthalten nur so genannte Fremdschlüssel mit den passenden Werten aus den ersten Spalten der Tabellen »images« und »categories«. Letztere sind jeweils als Primärschlüssel gesetzt und enthalten automatisch hochgezählte Sequenznummern. Die in der Tabelle »tags« definierten Felder führen also nur Fremdschlüssel, die in andere Tabellen verweisen. Sie enthalten - bis auf die eigentlich irrelevante Sequenznummer »id« - keine eigenen Daten.

Abbildung 1: Die Vermittlertabelle »tags« verbindet die Bildtabelle »images« und die Tag-String-Tabelle »categories«. Sie stellt damit eine n:n-Beziehung her: Jede Zeile in »tags« verbindet ein Bild mit einer Kategorie.

Abbildung 1: Die Vermittlertabelle »tags« verbindet die Bildtabelle »images« und die Tag-String-Tabelle »categories«. Sie stellt damit eine n:n-Beziehung her: Jede Zeile in »tags« verbindet ein Bild mit einer Kategorie.

Auf der Kommandobrücke

Diese Tabellenbeziehungen lassen sich mit Class::DBI einfach modellieren. Der Programmierer muss dann nicht mehr selbst die Relationen auflösen - die Objekte verhalten sich so, als ob sie statt des Fremdschlüssels direkt die referenzierten Daten enthielten. Durch Vererbung definiert das Camera-Store-Programm dazu drei eigene Klassen für die Reihen der beteiligten Tabellen. Für die Beziehungen zwischen den Klassen nutzt es die beiden Eigenschaften »has _a()« und »has_many()« der Vaterklasse »Class::DBI«.

Enthält eine Tabellenspalte keine eigenen Daten, sondern einen Fremdschlüssel, der auf Einträge in einer anderen Tabelle verweist, dann lässt sich diese Relation über eine Class::DBI-Methode fest im Objekt verankern:

KlasseTags->has_a("category",
   "KlasseCategories");


Ab diesem Zeitpunkt liefert die folgende Methode nicht mehr den Wert der Spalte »category« in » KlasseTags«, also nicht mehr den Fremdschlüssel, sondern ein Objekt der Klasse » KlasseCategories«:

KlasseTags->category();


Die Methode wählt die Zeile der Tabelle »categories«, deren Primärschlüssel zum Fremdschlüssel in der Tabelle »tags« passt. Das zurückgelieferte Objekt ist vom Typ » KlasseCategories« und enthält alle Daten der entsprechenden Zeile.

Diese Methode beschreibt die Relation in einer Richtung: von der Tabelle mit dem Fremdschlüssel zu der Tabelle, auf die sich der Fremdschlüssel bezieht. Häufig benötigt man aber die andere Richtung: Welche Einträge in einer anderen Tabelle verweisen auf eine bestimmte Zeile in der aktuellen Tabelle? Diese Beziehung lässt sich mit »has_many()« modellieren.

Diesen Artikel als PDF kaufen

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook