Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2006  »  07  »  Objekte statt Tabellen  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Datenbankanwendungen mit SQL Object

Objekte statt Tabellen

von Michael Göttsche
Erschienen im Linux-Magazin 2006/07

In objektorientiertem Programmcode wirken SQL-Abfragen wie Fremdkörper. Zudem unterscheiden sich die SQL-Dialekte verschiedener Datenbanken. Die Lösung: Der Objekt-Relational-Mapper SQL Object stellt ein einheitliches objektorientiertes Interface zur Verfügung.

Relationale Datenbanken und objektorientierte Programmiersprachen unterscheiden sich stark in der Art, wie sie Daten speichern. Eine Adressendatenbank enthält normalerweise eine eigene Tabelle für Personen und Adressen, einer Person lassen sich damit mehrere Adressen zuordnen.

Die einzelnen Tabellen wissen jedoch nichts übereinander. Erst durch eine mehr oder weniger komplexe SQL-Abfrage ist es möglich, die Daten zu einem logischen Datensatz zu verknüpfen. In objektorientierten Systemen hingegen ist die Zugehörigkeit von Objekten klarer festgelegt: Ein Adressen-Objekt ist einem oder beliebig vielen Personen-Objekten zugeordnet.

Diese unterschiedlichen Paradigmen erschweren das Arbeiten mit relationalen Datenbanken in objektorientierten Programmen. Abhilfe schaffen so genannte Object Relational Mapper. ORMs setzen die Tabellen einer relationalen Datenbank in Objekte um. Klassen entsprechen dabei Tabellen, die Datensätze erscheinen als Objekte, die Tabellenspalten als Objektattribute. Der ORM setzt Veränderungen an Klassen und Objekten im Hintergrund in SQL-Statements um und überträgt sie so in die Datenbank. Das Klasseninterface lässt sich also ohne SQL-Kenntnisse benutzen.

Die SQL-Dialekte der Datenbanksysteme unterscheiden sich trotz SQL-Standard oft erheblich. SQL Object abstrahiert von diesen SQL-Varianten und macht es auf diese Weise überflüssig, SQL-Code für verschiedene Datenbank-Engines von Hand zu schreiben.

SQL Object

Der für den Einsatz in Python konzipierte ORM SQL Object kommt bereits bei großen Projekten wie dem Ruby-On-Rails-Konkurrenten Turbogears [1] zum Einsatz. Der Python-Entwickler Ian Bicking hat SQL Object initiiert, inzwischen liegt Version 0.7 vor. Es unterliegt der LGPL und steht unter [2] zum Download bereit. Die Installation erfolgt mit »python setup.py install« oder mit dem Tool easy_install [3] über den Aufruf »easy_install SQLObject«.

SQL Object unterstützt weit verbreitete Datenbanken, darunter MySQL, PostgreSQL, SQLite und Firebird. Die Oracle-Unterstützung ist derzeit experimentell und noch nicht im Main-Branch enthalten.

Eine Musikdatenbank

Das folgende Beispiel verwendet SQLite als Datenbank-Backend. Wer eine andere Datenbank verwendet, muss aber den Quellcode bis auf die Connection-URL in Zeile 72 nicht verändern. Listing 1 enthält den Code für eine Musikdatenbank auf der Basis von SQL Object. Das einfache Python-Skript speichert Künstler mit die zugehörigen Genres und Alben in einer Datenbank.

Listing 1:
Musikdatenbank

01 from sqlobject import *
02 from optparse import OptionParser
03 
04 
05 class Artist(SQLObject):
06     name = StringCol(length=100)
07     albums = MultipleJoin('Album')
08     genres = RelatedJoin('Genre')
09 
10 class Genre(SQLObject):
11     name = StringCol(length=100)
12     artists = RelatedJoin('Artist')
13 
14 class Album(SQLObject):
15     name = StringCol(length=100)
16     artist = ForeignKey('Artist')
17     songs = MultipleJoin('Song')
18 
19 class Song(SQLObject):
20     name = StringCol(length=100)
21     album = ForeignKey('Album')
22 
23 def create_tables(option, opt_str, value, parser):
24     Artist.createTable(ifNotExists=True)
25     Genre.createTable(ifNotExists=True)
26     Album.createTable(ifNotExists=True)
27     Song.createTable(ifNotExists=True)
28 
29 def add_artist(option, opt_str, value, parser):
30     artists = Artist.select(Artist.q.name==value)
31     artist_exists = len(list(artists)) != 0
32     if not artist_exists:
33         artist = Artist(name=value)
34 
35 def del_artist(option, opt_str, value, parser):
36     artist = Artist.get(value)
37     artist.destroySelf()
38 
39 def add_genre(option, opt_str, value, parser):
40     genres = list(Genre.select(Genre.q.name==value))
41     genre_exists = len(genres) != 0
42     genre = None
43     if not genre_exists:
44         genre = Genre(name=value)
45     else:
46         genre = genres[0]
47     artist = Artist.get(parser.values.artist_id)
48     artist.addGenre(genre)
49 
50 def add_album(option, opt_str, value, parser):
51     artist = Artist.get(parser.values.artist_id)
52     album = Album(name=value, artist=artist)
53 
54 def list_artists(option, opt_str, value, parser):
55     artists = Artist.select()
56     for artist in artists:
57         print '''[%d] %s:
58         Album(s): %s
59         Genre(s): %s''' % (artist.id, artist.name, ','.join([i.name for i in 
60                            artist.albums]), ','.join([i.name for i 
61                            in artist.genres]))
62 
63 def find_artist_by_album(option, str, value, parser):
64     album = list(Album.select(Album.q.name==value))[0]
65     print 'Album artist:', album.artist.name
66 
67 def find_artists_by_genre(option, str, value, parser):
68     genre = list(Genre.select(Genre.q.name==value))[0]
69     print 'Artists of Genre %s:n%s' % (value, 'n'.join([i.name for i in 
69                                         genre.artists]))
70 
71 if __name__ == '__main__':
72     connection = connectionForURI('sqlite:///home/michael/musikdb/sqlobject_example.sql')
73     sqlhub.processConnection = connection
74 
75     parser = OptionParser()
76     parser.add_option('-c', '--create', action='callback', callback=create_tables,
77                       help='Create necessary tables in the database')
78     parser.add_option('--add-artist', action='callback', callback=add_artist,    
79                  type='string',help='Add new artist to the database')
80     parser.add_option('--del-artist', action='callback', callback=del_artist,    
81                 type='int', help='Delete artist with the specified ID')
82     parser.add_option('--artist-id', dest='artist_id', help=
83                      'The artist ID for the command following the ID parameter')
84     parser.add_option('--add-genre', action='callback', callback=add_genre,               
85                       type='string', help='Add a genre to an existing artist')
86     parser.add_option('--add-album', action='callback', callback=add_album,
87                       type='string', help='Add an album to an existing artist') 
88     parser.add_option('-l', '--list', action='callback', callback=list_artists,
89                       help='List artists, their genres and albums')
90     parser.add_option('--artist-by-album', action='callback', 
91                          callback=find_artist_by_album, type='string',
92                          help='Find the artist of a given album')
93     parser.add_option('--artists-by-genre', action='callback', 
94                       callback=find_artists_by_genre,
95                       type='string', help='Find artists of a given genre')
96 
97     (options, args) = parser.parse_args()

Die über Kommandozeilenargumente gesteuerte Anwendung erlaubt es, Daten einzugeben, auszulesen und zu durchsuchen. Auf eine Löschfunktion für Alben und Genres wurde der Einfachheit halber verzichtet. Abbildung 1 zeigt die Dateneingabe sowie einige Datenbankabfragen auf der Konsole.

Sie können diesen Artikel als PDF für 99 Cent kaufen. Klicken Sie dazu einfach auf eine der beiden Bezahloptionen Paypal oder ClickandBuy.


Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Modulare Architektur Kexi - Datenmanagement in KOffice
Elefantenrennen Die neuen Features in PostgreSQL 8.0
Ein Elefant als Basis Die PostgreSQL-Erweiterung Postgis und freie GIS-Programme
Schädlingsbekämpfung Perl-Skript bewahrt Webforen und Blogs vor Spamflut
Andockmanöver Open Office zapft externe Datenbanken an
Frisch aufgebrüht Netbeans 6.0 und Eclipse 3.3 im Vergleich
Whitepaper
Usage Landscape Enterprise Open Source Data Integration

Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.

Download PDF (Registrierung erforderlich)
Daten Migration - Eine Publikation von Bloor Research

Datenmigrationsprojekte überschreiten häufig das Budget, neigen zu Verzögerung und werden unter Umständen komplett abgebrochen. Bloor Research ist eines der weltweit führenden IT-Forschungs-, Analyse- und Beratungsunternehmen und wird in dem vorliegenden White Paper die wichtigsten Aspekte dieser Problematik näher beleuchten. Ferner werden praktische Empfehlungen für erfolgreiche Migrationsprojekte gegeben, die Sie auf Ihr nächstes Projekt übertragen können.

Download PDF (Registrierung erforderlich)
Kommentare (0)