((short description what this page is about))
Dann habe ich mich über QPath bzw. XQuery informiert und die Abspeicherung der Stringrepräsentationen der MPE in einer XML Datenbank in Betracht gezogen. Dazu habe ich das durch die Stringrepräsentation eines MPE gegebene XML Dokument aufgrund der in verschiedenen Quellen angegebenen Kriterien als ein semistrukturiertes, dokumentenzentriertes XML-Dokument klassifiziert. Dem entsprechend habe ich Überlegungen bezüglich einer geeigneten Speicherung der XML-Dokumente und Architektur einer möglichen verwendeten (nativen) XML-Datenbank angestellt.(siehe Grafik "Speicherung und Architektur von XML Datenbanken").
Wie sieht es mit der Performance von nativen XML-Datenbanken aus?
Wie mächtig sind die XML-Anfragesprachen, was lässt sich damit realisieren?
Weitere Vertiefung in das Gebiet der nativen XML Datenbanken, mit Fokus auf der nativen, modellbasierten XML Datenbank Apache Xindice.
Überlegungen zur Erzeugung eines XML Dokuments, in dem die komplette Information des EventPackage-Objekts mit seinen Attributen enthalten ist, um dieses XML Dokument dann in die Datenbank zu schreiben und daraus auch wieder das EventPackage - Objekt rekonstruieren zu können.
Alle Typen von MPEs haben eine feste gemeinsame Menge von Standardattributen, welche in einer Relation gespeichert werden sollen.
Diese Attribute werden voraussichtlich sein:Die typspezifischen Attribute eines MPE werden dann entweder in einer weiteren Tabelle gespeichert und entsprechend mit dem Eintrag in der Tabelle der Standardattribute verknüpft. Eine andere Möglichkeit wäre, für jeden MPE Typ eine Tabelle anzulegen, in der sowohl die Standardattribute des MPE als auch die Detailattribute dieses MPE Typs gespeichert werden.
Weiterhin muss das DataBaseTargetModule die Standardattribute in geeigneter Form aus einem EventPacket (insbes. aus der ArgList) extrahieren können. Gleiches gilt für die Detailattribute.
IM ECGLab wird XML zum Datentransport verwendet, es handelt sich also um datenzentrierte Dokumente, mit ziemlich regelmäßiger Struktur und das Interesse liegt mehr oder weniger auf den im XML Dokument enthaltenen Daten und nicht auf dem gesamten XML Dokument.
Daten werden üblicherweise in relationalen Datenbanken gespeichert, weshalb ich mich für das DBMS MySQL entschieden habe. Läge mein Interesse auf der Speicherung von ganzen XML Dokumenten, so wäre eine nativen XML Datenbank vorzuziehen gewesen.
Um Daten zwischen XML Dokumenten und einer Datenbank transferieren zu können, muss das Schema des XML Dokuments auf das Datenbankschema abgebildet werden. Eine Software für den Datentransfer baut dann auf dieser Abbildung auf.
Generell gesehen gibt es zwei Möglichkeiten der Abbildung von XML Schemata in Datenbankschemata:
Das Framework Castor geht den Weg über die Generierung von Java aus XML und bildet diese Java Klassen dann mit Hilfe einer Mapping Datei in die Datenbank ab. Die Generierung von Java Klassen, falls das im ECG überhaupt wirklich in geeigneter Form möglich wäre, stellt ansonsten aber keinen Nutzen dar.
In einem Artikel über Hibernate 3 (http://www.devx.com/Java/Article/27896) las ich, dass Hibernate nun auch das direkte Abbilden von XML in eine Datenbank unterstützt, also ohne Generierung von Java, sondern lediglich mit Hilfe einer Mapping - Datei. Dabei gilt, dass Hibernate XML Dokumente sozusagen wie Java Objekte behandelt und die einzelnen Elemente aus dem XML Dokument mit der entsprechenden Mapping - Datei dann auf Tabellen und Spalten abbildet. Aber auch in der Hibernate Doku, welche zu Thema XML Mapping eher knapp gehalten ist steht, dass dieses noch ein experimetelles Feature "under extremely active development" ist. Doch da ich diesen Ansatz des direkten XML - Mappings in die Datenbank für die Zwecke des ECG Labs ziemlich optimal finde, habe ich mich in das Thema hereingearbeitet und die entsprechende Hibernate "Umgebung" mit Datenbank, Konfigurations- und Mapping - Datei aufgebaut. Doch leider ist es mir nicht gelungen, ein XML Dokument entsprechend einer Mapping - Datei einzulesen und zu verarbeiten. Und obwohl ein Framework an sich eine schöne Sache ist und zur Minimierung von Fehlern und Aufwand beiträgt, sah ich den Aufwand für ein "experimentelles" Feature, dessen Funktionalität nicht einmal wirklich sicher gestellt ist, irgendwann dann nicht mehr gerechtfertigt. Deswegen werde ich jetzt von der Verwendung eines Frameworks absehen und die Abbildung von Events komplett selbst implementieren, was ich dann auch entsprechend besser auf die Anwendung im ECG Lab anpassen kann.Optionale Elements entsprechen einem möglichen NULL Wert in der Datenbank. Ein Problem stellt sich jedoch bei der dynamischen Generierung der Parameter für den "INSET INTO.." - String um die jeweilgen Daten aus einem XML-Dokument in die Datenbank einzufügen. Die Elemente in diesem String müssen der Reihenfolge der Tabellenspalten entsprechen. Doch extrahierte ich ganz schlicht nacheinander die Daten aus den XML Dokumenten, so erhalte ich keine Information aus den XML Dokumenten darüber, ob optionale Elemente in dem jeweiligen XML Dokument nun gerade vorhanden sind oder nicht. Ich kann mich also nicht mehr darauf verlassen, dass ich überhaupt für alle Spalten der Datenbanktabelle Daten aus dem XML-Dokument erhalte, denn NULL Werte stehen nicht im XML-Dokument. D.h. ich müsste explizit für jedes ELement im XML-Dokument den Namen und den Wert herausziehen und dass ganze dann mit den Informationen aus dem entsprechenden XML-Schema abgleichen, um so herauszufinden für welche evtl. nicht vorhandenen optionalen Elemente in diesem Dokument NULL Werte in der Datenbanktabelle eingefügt werden müssen.
Diese Frameworks (z.B. Apache XMLBeans), welche XML-Schemata in 'Objektschemata' abbilden, sollen jedoch den Zugriff und das Modifizieren von Daten in (datenzentrierten) XML Dokumenten aus einer Anwendung heraus erleichtern.
Diese Abbildung von XML-Schemata auf Objektschemata finde ich für die betrachteten Zwecke im ECG-Lab nicht passend, denn zum einen geht es hierbei nicht um den Zugriff auf Daten in einem XML Dokument und zum anderen wäre es schlecht für die Dynamik bezüglich veränderter oder hinzukommender MSDT - Schemata, wenn aus diesen erst Klassen und *.jar Files generiert und dann entsprechend verwendet werden müssten.
Der zentrale Punkt ist das extrahieren von Informationen aus einem XML-Schema, wobei ich den Weg gewählt habe das jeweilige Schema mit dem Apache Xerces Parser zu parsen, um dann die entsprechende Information zu erhalten und in geeigneter Weise zu speichern.
Bisher habe ich eine Art 'Infrastruktur' von Klassen mit verschiedenen Verantwortlichkeiten aufgebaut:Diese 'Infrastruktur' ist aber noch nicht komplett implementiert und auch nicht getestet und ich vermute, dass das extrahieren und speichern der richtigen von Informationen aus einem XML - Schema nicht so ganz so klappen wird wie ich es brauche und wie ich es mit dem Apache Xerces J2 und dessen Schema API zu implementieren versuche.
Diese widerum übergibt das EventPacket einer Instanz der Klasse CreateSql, welche mit Hilfe der Proxyklasse für das EventPacket (ValidEventPacketProxy) die Daten aus dem EventPacket extrahiert und die entsprechenden "INSERT INTO.." Strings für die Einfügeoperation der Datenbank generiert.
Dabei wird auch ein Datenbank Proxy (DatabaseProxy) verwendet, der vor der Generierung der SQL-Strings aus der Datenbank die Metainformationen der entsprechende Tabelle holt und diese (die Spaltennamen) in der selben Reihenfolge wie in der Tabelle vorkommend, in einen Vector schreibt. Für jedes Element des Vectors (also jede Spalte der Tabelle) wird dann bei der Generierung des SQL-Strings mit Hilfe der Klasse ValidEventPacketProxy geschaut, ob in dem XML Dokument auch ein Element mit dem entsprechenden Namen vorhanden ist. Falls ja, wird von der Methode ValidEventPAcketProxy.getElementValue(String elementName) der entsprechende Wert zurück geliefert und in den SQL-String eingetragen. Ist in dem XML Dokument kein entsprechendes Element vorhanden, weil es sich beispielsweise um ein optionales XML-Element handelt, so wird von der Methode ValidEventPAcketProxy.getElementValue(String elementName) NULL zurück geliefert und auch dieses in den SQL-String eingetragen. Somit richtet sich die Einfügeoperation nach den in der Tabelle vorhandenen Spalten, und für Spalten optionaler Elemente des XML-Dokuments wird ggf. ein null Wert in die Datenbank eingetragen.
Noch nicht realisiert ist die dynamische Anpassung und Generierung der Datenbanktabellen bei veränderten oder neu eingeführten MSDT XML-Schemata.
Um eine Art Proxy für die msdt Schemata zu entwerfen, über den man dann Informationen über das Schema selbst in geeigneter Form erhalten kann, habe ich mir das Apache Projekt XMLBeans genauer angesehen.
Zunächst einmal habe ich mir einen Überblick verschafft, wofür diese Technologie eingentlich entworfen wurde, was sie kann und welche Möglichkeiten sie einem bietet die gewünschten Ziele zu erreichen.
XMLBeans erleichtert den Zugriff auf XML, indem es das XML an Java Klassen bindet und dann über 'bean-like' setter- und getter- Methoden den Zugriff auf das XML ermöglicht.
Die XMLBeans API bietet jedoch auch ein XML Object Model, über welches man Informationen über ein XML Schema selbst erhalten kann. Und genau diesen Teil fand ich für die Idee eine 'Schema-Proxys' interessant und habe genauer untersucht inwieweit diese Möglichkeiten für den Gebrauch im ECG_Lab geeignet sind.
Man kann die XMLBeans API in drei Kategorien unterteilen:Ich habe die SchemaType API für ein geeignetes Mittel empfunden um aus den msdt XML Schemata geeignete Informationen zu erhalten. Beispielsweise um Schema-Elemente und -Datentypen mit den Datenbanktabellen abzugleichen und so das dynamische Anpassen der Datenbanktabellen an modifizierte Schemata umzusetzen.
Nachdem ich mich eine Weile mit dem Komponenten- und Typsystem der XMLBeans API auseinandergesetzt habe, habe ich nun einen ersten Entwurf des SchemaProxys fertiggestellt und getestet, der ein beliebiges Schema einliest, es 'compiliert' (Datenmodell aufbaut) und rekursiv die Baumstruktur des XML Schemas durchläuft. Dabei wird jeder Knoten auf gewisse (alle möglichen) Eigenschaften überprüft und in Abhängigkeit davon wird der Algorithmus fortgesetzt.So lange bis alle einfachen Elemente (Blätter des XML Schema Baums) erreicht sind und mit den entsprechenden Namen und Datentypen ausgegeben werden.
Um dieses zu veranschaulichen habe ich eine Grafik erstellt, die diesen Algorithmus skizziert (XSDSchema.pdf im Anhang).
Beim extrahieren eines Elements aus einem XML Schema wird zunächst nur der Name und der XmlDatentyp gesetzt. Dann wird dieses Element einer Methode übergeben, welches dem XML Datentyp des Elements den entsprechenden Sql Datentyp zuordnet und diesen in das Sql Datentyp Attribut des Elements schreibt.
Auf Grundlage solcher Elemente können dann XmlSchema und existierende Tabellen verglichen und Tabellen ggf. erstellt oder angepasst werden. Dazu liefert eine Klasse DBCommunicator durch entsprechende Informationen, welche sie ebenfalls durch Instanzen der Klasse Element zurück gibt.
Nun sind vorerst verschiedene Punkte zu klären,Die Methode getSchemaProperties liefert als Rückgabewert einen Vector, welcher für ein msdt Schema alle nötigen Tabellen mit ihren jeweiligen Spaltennamen und -typen enthält, um Instanzen (XML Dokumente) des Schemas in der Datenbank zu speichern. Gleichzeitig generiert die Methode die sog. TableInformation für jedes Schema. TableInformation ist eine mit dem Singleton-Pattern implementierte Klasse deren Instanz in einer HasMap zu jedem msdt-Typ die Namen der zu diesem msdt-Typ gehörigen Tabellen hält. damit ist festgehalten, welche Tabellen man bein Einfügen oder Extraherien eines msdt Typs in die bzw. aus der Datenbank betrachten muss.
Da neue Eventtypen mit entsprechenden Schemata hinzu kommen können oder existierende Eventtypen erweitert werden können, müssen beim Start oder nach dem Ändern bzw. Hinzufügen eines Eventtyps die Schemata mit den in der Datenbank existierenden Tabellen abgeglichen werden. D.h. es werden Änderungen in den Schemata in Richtung Datenbank nachvollzogen.
Das geschieht, in dem für jedes im msdt Ordner liegende Schema folgende Operationen vollzogen werden:
Eine Grafik welche die oben berschriebenen Vorgänge skizziert befindet sich im Anhang.
Die Verknüfpung aller zu einem Event gehörenden Tabellen geschieht über eine Spalte linkID. Diese linkID Spalte ist der Primärschlüssel der commondata Tabelle und ein Fremdschlüssel in allen anderen generierten Tabellen. Beim Einfügen in commondata wird dieser Primärschlüssel von der Datenbank generiert, als Variable zurückgegeben und wird dann bei den Einfügeoperationen in allen anderen zu diesem Event gehörenden Tabellen als Wert für die Fremdschlüsselspalte übergeben.
Ausstehende Problemstellungen: