Tamino XML-Datenbank

Werbung
Tamino XML-Datenbank
Technologie Memo
April 2005
 Dr. Arno Schmidhauser
Tamino XML-Datenbank
Inhalt
1
2
3
4
5
6
Referenz
Einsatzgebiete
Features
Datenbank-Organisation
Kommunikation mit Tamino
Abfragesprachen
6.1 XPath, XQuery
6.2 XUpdate
6.3 Trigger
7 Indexe
8 Transaktionsverhalten
9 Entwicklungs-Tools
10
Verschiedenes
11
Beispiel HTTP-Anbindung
12
Beispiel DOM-Anbindung
Technologie Memo
Arno Schmidhauser
3
3
3
4
5
6
6
6
7
7
8
8
8
9
15
2
Tamino XML-Datenbank
1 Referenz
Die folgenden Kapitel beziehen sich auf die XML-Datenbank Tamino, Version 4.2.1, der Firma Software AG, Deutschland: www.tamino.de oder
www.softwareag.com.
2 Einsatzgebiete
ƒ
Dokumentzentrierte und semistrukturierte Informationssysteme, beispielsweise elektronische Patientenakte, Ablage von Publikationen, Verträgen, Kundendokumenten usw. Fulltext-Retrieval ist ein Stärke von
Tamino.
3 Features
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
ƒ
Native XML-Datenbank für High End Performance. Transaktionsorientiert, mit vielen Monitoring- und Verwaltungstools.
Die Abfragesprache XQuery des W3 Konsortiums wird grösstenteils unterstützt. Der Name 'XQuery' ist nicht zu verwechseln mit 'X-Query',
der ältern Abfragesprache von Tamino, die im Wesentlichen eine Erweiterung von XPath 1.0 darstellt.
Zusätzlich zu XQuery sind mächtige Funktionen für das FulltextRetrieval verfügbar (allerdings nicht in der Syntax des XQuery Fulltext
Standards). Die Funktionen umfassen das Suchen nach benachbarten
Worten, phonetische Suche, Stammform-Suche, Thesaurus, Patternmatching.
Als Erweiterung zu XQuery wird eine XML-basierte Modifikationssprache
angeboten, so dass mit XQuery von Tamino im einheitlichen "Look and
Feel" Daten verwaltet werden können, in Analogie zu den SQL-Befehlen
select/update/delete/insert.
API's für Java, .net, C, PHP und JScript.
Java API's: SAX, DOM und DOM4J sowohl für lesenden wie schreibenden Zugriff auf die zugrundeliegende Datenbank. Die zu verarbeitenden
Daten können mittels Query vorselektiert und dann geändert oder gelöscht werden.
Benutzerverwaltung mit User, Group und ACL's. Die Authorisierung findet auf XML-Knotenebene (!) statt. Authentisierung über Zertifikate via
vorgeschalteten Webserver.
Technologie Memo
Arno Schmidhauser
3
Tamino XML-Datenbank
4 Datenbank-Organisation
ƒ
Auf Ebene Betriebssystem besteht eine 1 zu 1 Beziehung zwischen Datenbank und Prozess. Die Datenbank enthält eine Anzahl so genannter
Collections. Eine Collection ist eine Sammlung von XML-Dokumenten.
Es gibt System-Collections und es gibt Benutzer-Collections (analog zu
relationalen Datenbanken mit System-Tabellen und Benutzer-Tabellen).
Datenbank-Serverprozess
Datenbank
Collection X
Schema A
Collection Y
Schema B
Schema C
Collection mit a
und b Dokumenten
Schema D
Collection mit c
und d Dokumenten
ƒ
Die Hierarchische Organisation ist wie folgt:
Datenbank Æ Collection Æ Dokument Æ Inhalt
ƒ
Es können beliebig viele Benutzer-Collections errichtet werden. Für jede Collection können mehrere XML Schema definiert werden. Dokumente in den Collections können, aber müssen nicht einem Schema
zugeordnet sein. Ob nur schema-konforme Dokumente zugelassen sind
oder nicht, wird beim Erstellen der Collection festgelegt.
ƒ
ƒ
Ein Dokument ist die Grundeinheit, welche in eine Collection eingefügt,
geändert oder gelöscht wird. Beispielsweise werden in einer Collection,
welche einen Bücherkatalog darstellt, book-Dokumente eingefügt.
Die Schema-Definition in Tamino hat einige Erweiterungen gegenüber
der Spezifikation des W3C. Beispielsweise gibt es ein so genanntes
doctype-Element, welches den Namen des Root-Elementes eines Dokumentes identifiziert (analog zum DTD Doctype). Ausserdem werden
Index-Definitionen, Angaben zur Kompression usw. innerhalb des
Schema vorgenommen. Der Namespace tsd: kennzeichnet die Tamino-spezifischen Angaben von den allgemeinenen Angaben (Namespace
xs).
Technologie Memo
Arno Schmidhauser
4
Tamino XML-Datenbank
5 Kommunikation mit Tamino
Der Datenbank-Server in Tamino heisst X-Machine. Grundsätzlich gibt es
zwei Möglichkeiten mit der X-Machine zu kommunizieren: a) über eine
sehr enge, einfache URL/HTTP-Schnittstelle via Apache Server. b) über
Programmiersprachen-Interfaces wie DOM für Java oder C# etc. Aus Sicht
der X-Machine sind beide gleich und führen letzlich über das taminospezifsche Protokoll XTS. Aus Sicht des Datenbank-Clients sind sie aber
verschieden.
Any Client Type
Java, C, C# Clients
URL/HTTP calls with XMachine commands
Java, C, C# Libraries
e.g. DOM Interface
Apache
X-Modul
Tamino Protocol
(XTS over TCP/IP)
X-Modul
Tamino Protocol
(XTS over TCP/IP)
X-Machine
Die Kommunikation via URL/HTTP sei an folgendem Beispiel illustriert,
welches die Abfrage input()/book/title an die Datenbank schickt:
http://host/tamino/mydb/mycollection?_xquery=input%28%29%2Fboo
k%2ftitle
Die so genannten X-Machine Commands (im Beispiel fettgedruckt) sind
URL-Parameter, welche alle mit einem '_' beginnen. Weitere Beispiele sind
_process, _delete zum Einfügen respektive Löschen von Dokumenten.
Auf diesem Weg können auch Sessions erzeugt, Transaktionen bestätigt
oder zurückgefahren werden, Administrationsbefehle abgesetzt werden
usw.
Ohne weiter Angabe läuft obiges Beispiel "sessionless" ab. Jede Anfrage
an die Datenbank wird in diesem Fall automatisch bestätigt (committed).
Sobald aber als Parameter _connect=* spezifiziert wird, startet der Tamino-Server eine Session, die bis zum expliziten Beendigungsbefehl mit
_disconnect weiterläuft. Der _connect-Befehl liefert in Form eines HTTPHeaders eine Session ID und einen Session Key zurück. Diese beiden
müssen bei jedem nachfolgenden Aufruf wieder mitgegeben werden. Die
Session ID identifiziert die laufende Session, der Session Key ist lediglich
eine fortlaufende Nummer für den jeweils nächsten Aufruf. Die beiden Pa-
Technologie Memo
Arno Schmidhauser
5
Tamino XML-Datenbank
rameter müssen als URL-Parameter _sessionid und _sessionkey mitgegeben werden.
6 Abfragesprachen
6.1 XPath, XQuery
ƒ
ƒ
ƒ
XQuery ist die Hauptausrichtung in den neuen Version von Tamino
(Genauer Produktname XQuery 4) Daneben wird ein Dialekt von XPath
mit dem schwer zu unterscheidenden Produktname X-Query angeboten.
Der Ausgangspunkt für eine XPath- oder XQuery-Abfrage, beispielsweise /book/title, ist eine Collection von XML-Dokumenten ( '/' ) . Das
Eintrittskonstrukt in die Datenbank bei einer Abfrage ist daher meist
input()/ oder collection( 'mycollection' )/ . Im ersten Fall wird
die bei der Verbindung angegebene Collection verwendet, im zweiten
Fall eine explizit genannte Collection.
Abfragen können über mehrere Collections hinweg durchgeführt werden, eine Abfrageoptimierung findet jedoch nur innerhalb der Collection
statt.
6.2 XUpdate
Um XML-Daten auch über die Abfragesprache ändern zu können, hat Tamino eine spezielle Erweiterung von XQuery geschaffen. Diese ist im Moment zwar noch proprietär, wird aber mit grosser Wahrscheinlichkeit einen
entsprechenden Entwurf des W3C wesentlich beeinflussen. Beispiele von
Update-Befehlen:
update
for $b in input()/book
where $b/title = "didle dum dum"
do insert <subtitle>a introduction</subtitle> into $b/title
update
for $b in input()/book
where $b/title = "didle dum dum"
do insert <subtitle>a introduction</subtitle> following
$b/title
update
for $b in input()/book
where $b/title = "didle dum dum"
do replace $b/title/text() with "Learning XML"
update
for $b in input()/book
do delete $b/subtitle
Technologie Memo
Arno Schmidhauser
6
Tamino XML-Datenbank
6.3 Trigger
Tamino unterstützt Trigger. Beim Einfügen, Ändern, Löschen eines Dokumentes wird eine programmierte Funktion aufgerufen (Server Extension,
in Java, C# und weitere).
7 Indexe
Die Bereitstellung von indexierten Daten ist unabdingbar für eine Datenbank. Tamino hat ein gut ausgebautes Indexsystem, um auch komplizierte
Abfragen in grossen Collections mit guter Performance durchzuführen. Folgende Index-Grundarten kommen zum Einsatz:
ƒ
ƒ
ƒ
ƒ
ƒ
Standard-Index. Eingang: Textwert eines Knotens. Ausgang: Zugehörige Dokument-Referenz(en). Struktur: Baumartig, z.B. B*. Nutzen: Abfragen, wie /book/title[.= 'Learning XML'] werden beschleunigt. Der Index wird auf einen bestimmten Knotentyp gesetzt, und
dessen Inhalt wird dann indexiert. Das Resultat der Indexsuche ist aber
der Dokumentknoten, in dem sich der gesuchte Inhalt befindet. Falls
der Index auf einen Knoten gesetzt wird, der weitere Kind-Knoten enthält, wird der gesamte Knoten atomisiert vor der Indexierung.
Text-Index. Eingang: Wort oder Wortpattern innerhalb des Textwertes
eines Knotens. Ausgang: Zugehörige Dokument-Referen(en). Struktur:
Baumartig, z.B. B*. Nutzen: Abfragen, wie for $b in $input()/book
where contains($b/title, 'Learning') return $b. Ein Text-Index
teilt Knoteninhalte in Worte und Wortfragmente auf. Der DatenbankAdministrator kann die Indexierung stark beeinflussen: Positive und
negative Wortliste, Fragment-Indexierung, Wortstamm-Indexierung.
Ansonsten ähnlich dem Standard-Index.
Multipath-Index. Eingang: Textwert eines Knotens. Ausgang: Eine
Menge von Knotensequenzen, welche jede eine rückwärts verkettete
Liste vom End-Knoten der Suche bis zum Dokument-Wurzelknoten darstellt. Nutzen: Abfragen mit Wildcards im Pfadausdruck werden wesentlich beschleunigt, zum Beispiel /book//title, oder /*/*/title.
Es sind sowohl Standard-Multipath- wie Text-Multipath-Indexe möglich.
Ein Referenz-Index ist eine Verfeinerung des Standard-Index, in dem
irgend ein Knoten (nicht nur das Dokument) als Referenzknoten definiert werden kann, und unterhalb des Referenzknotens mehrere Pfade
indexiert werden dürfen. Beispielsweise könnte der Referenzknoten
/book/author sein. Die zu indexierenden Pfade könnten
author/firstname und author/lastname sein. Damit wäre eine Abfrage
der Art /book/author[ firstname='Steven' and lastname = 'Holzner']
extrem schnell, weil nur Autoren-Elemente auszugeben sind, und Bedingungen auf den zwei indexierten Unterpfaden gesetzt sind. Es sind
sowohl Standard-Referenz- wie Text-Referenz-Indexe möglich.
Struktur-Index. Eingang: Elementname. Ausgang: Zugehörige Dokument-Referen(en). Nutzen: Dokumentsammlungen mit sehr offenem
Technologie Memo
Arno Schmidhauser
7
Tamino XML-Datenbank
ƒ
Schema, so dass bereits der Elementname in einer Abfrage eine relevante Einschränkung der Ergebnismenger darstellt.
Indexierung ist nur möglich, wenn ein Schema für die zu indexierenden
Dokument definiert ist.
8 Transaktionsverhalten
Bezüglich Concurrency Control bietet Tamino 5 Isolationsgrade: uncommittedDocument (entsprechend READ UNCOMMITTED bei SQL), committedCommand (entsprechend READ COMMITTED bei SQL), stableDocument
(entsprechend REPEATABLE READ bei SQL) und serializable.
9 Entwicklungs-Tools
ƒ
ƒ
ƒ
Der X-Plorer ermöglicht die interaktive Bedienung, Durchforstung und
Pflege der Datenbank. Einige Interfaces sind auch als HTML-Seiten verfügbar und bedürfen damit keiner Installation.
Ein Schema Editor ermöglicht die Definition eines oder mehrere XML
Schema, dem die einzufügenden XML-Dokumente genügen müssen.
Mit dem Tamino Manager können Datenbanken und Benutzer angelegt, Server-Parameter eingestellt, aktive Sessions und Transaktionen
überwacht und viele Management-Aufgaben durchgeführt werden. Der
Tamino-Manager ist webbasiert.
10 Verschiedenes
ƒ
ƒ
Ist Schema Evolution unterstützt?
Ja. Das neue Schema sollte so sein, dass bestehende Dokument nicht
ungültig werden. Der Benutzer ist für die Validierung der bestehenden
Dokumente gegen das neue Schema verantwortlich.
Gibt es eine Art Primärschlüssel?
Ja. Jedes Dokument bekommt per default ein internes Attribut ino:id
mit. Dieses ist mit der Funktion tf:getInoId() abrufbar. Dieser sollte
allerdings nur für kurzfristige Programmatische Zwecke verwendet
werden, wie das Lesen in eine Applikation und Zurückschreiben auf die
Datenbank. Für permanente Beziehungen zwischen Dokumenten wird
mit Vorteil ein eigener Primärschlüssel definiert.
Technologie Memo
Arno Schmidhauser
8
-----------------------------------------------------------------------------------------------------------*/
import java.io.*;
import java.net.*;
import java.util.*;
import javax.xml.xpath.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
11.4.2005 Arno Schmidhauser
History
<student id="1">
<name>Hans Besserwisser</name>
<klasse>ead01</klasse>
<faecher>
<fach>
<titel>Java für Profis</titel>
<ects>2</ects>
</fach>
...
</faecher>
</student>
This program relies on a student document with the following structure in the tamino database.
Example documents can be added with http://swsdb.hta-be.bfh.ch/TaminoXQuery.html
This program does the following steps:
1) send a query to the tamino database to retrieve all students who belong to a "klasse".
2) add a <fach>...</fach> entry to each student document
3) write back the student documents to the database
/* --------------------------------------------------------------------------------------------------------
11 Beispiel HTTP-Anbindung
Technologie Memo
}
Arno Schmidhauser
10
// get session from database
String queryURL = collectionUrl + "?_connect=*&_isolationLevel=serializable";
URLConnection uc = (new URL( queryURL )).openConnection();
sessionid = uc.getHeaderField( "X-INO-Sessionid" );
sessionkey = uc.getHeaderField( "X-INO-Sessionkey" );
// create transformer for transforming DOM tree with XSL stylsheet
TransformerFactory trafactory = TransformerFactory.newInstance();
transformer = trafactory.newTransformer();
transformer.setOutputProperty( "omit-xml-declaration", "yes" );
DocumentBuilderFactory docfactory = DocumentBuilderFactory.newInstance();
docfactory.setNamespaceAware( true );
builder = docfactory.newDocumentBuilder();
/**
* Constructor.
*/
public TaminoDomDocumentManager( String collectionUrl ) throws Exception
{
this.collectionUrl = collectionUrl;
/**
* TaminoDocumentManager retrieves student documents from database, edits them,
* and writes them back to database.
*/
public class TaminoDomDocumentManager
{
protected String
collectionUrl;
protected String
sessionid;
protected String
sessionkey;
protected DocumentBuilder builder;
protected Transformer
transformer;
protected static String
urlEncoding = "iso-8859-1";
// since no http encoding header is sent, tamino-apache
// is expecting iso-8859-1 by default.
import javax.xml.transform.stream.*;
import org.w3c.dom.*;
Tamino XML-Datenbank
Technologie Memo
}
Arno Schmidhauser
// send Query
Document doc = sendQuery( updQuery );
commit();
return doc;
11
updQuery = updQuery.replaceAll( "\\$param1", serializeDOM( student ) );
// prepare update query
String updQuery = " update "
+ " let $p := $param1 "
+ " for $s in input()/student "
+ " where $s/@id = $p/@id "
+ " do replace $s with $p ";
/**
* save student record back to database
*/
protected Document saveStudent( Element student ) throws Exception
{
}
// send Query
Document doc = sendQuery( getQuery );
commit();
return doc;
/**
* retrieve studentlist from database
*/
protected Document getStudents( String klasse ) throws Exception
{
// prepare query to retrieve student
String getQuery
= " for $s in input()/student "
+ " where $s/klasse = '$param1' "
+ " return $s ";
getQuery = getQuery.replaceAll( "\\$param1", klasse );
Tamino XML-Datenbank
Technologie Memo
Arno Schmidhauser
/**
* disconnect session
*/
protected Document disconnect() throws Exception
{
// compose disconnect url
String disconnectUrl = collectionUrl + "?"
+ "_sessionid=" + sessionid + "&"
+ "_sessionkey=" + sessionkey + "&"
+ "_disconnect=*";
/**
* commit transaction
*/
protected Document commit() throws Exception
{
// compose commit url
String commitUrl = collectionUrl + "?"
+ "_sessionid=" + sessionid + "&"
+ "_sessionkey=" + sessionkey + "&"
+ "_commit=*";
// send request
return sendUrlRequest( commitUrl );
}
12
/**
* send XQuery and wrap result into DOM document
*/
protected Document sendQuery( String query ) throws Exception
{
// open url connection to tamino database and execute query
String queryUrl = collectionUrl + "?"
+ "_sessionid=" + sessionid + "&"
+ "_sessionkey=" + sessionkey + "&"
+ "_xquery=" + URLEncoder.encode( query, urlEncoding );
return sendUrlRequest( queryUrl );
}
Tamino XML-Datenbank
Technologie Memo
Arno Schmidhauser
/**
* get next id value. database must contain a document named 'counter'
/**
* serialize DOM tree to string
*/
protected String serializeDOM( Node n ) throws Exception
{
try {
// write DOM tree to string
DOMSource
source = new DOMSource( n );
ByteArrayOutputStream bos = new ByteArrayOutputStream();
StreamResult result = new StreamResult( bos );
transformer.transform( source, result );
return bos.toString( "utf-8" );
}
catch( Exception e ) { return "<serializationError/>"; }
}
}
// parse input stream to DOM document
Document doc = builder.parse( is );
is.close();
return doc;
/**
* sendUrl
*/
protected Document sendUrlRequest( String urlReq ) throws Exception
{
URLConnection uc = (new URL( urlReq )).openConnection();
sessionkey = uc.getHeaderField( "X-INO-Sessionkey" );
InputStream is = uc.getInputStream();
}
// send request
return sendUrlRequest( disconnectUrl );
Tamino XML-Datenbank
13
Technologie Memo
Arno Schmidhauser
// get students from database
Document doc = docman.getStudents( klasseArg );
System.out.println( "students retrieved." );
14
/**
* main
*/
public static void main( String argv[] )
{
if ( argv.length != 4 ) {
System.out.println( "Usage: TaminoDomDocumentManager <collectionUrl> <klasse> <fachTitel> <ectsPkte> " );
System.out.println( "Example: TaminoDomDocumentManager http://swspc069/tamino/swsdb/swspublic ead01 datenbanken 5
" );
System.exit( 1 );
}
try {
String collectionUrl = argv[0];
String klasseArg
= argv[1];
String fachArg
= argv[2];
String punkteArg
= argv[3];
TaminoDomDocumentManager docman = new TaminoDomDocumentManager( collectionUrl );
}
Document confirmation = sendQuery( incQuery );
Document doc = sendQuery( getQuery );
String cVal = doc.getElementsByTagName( "counter" ).item(0).getFirstChild().getNodeValue();
System.out.println( cVal );
return cVal;
String getQuery = " input()/counter";
* which contains the current id value e.g.: <counter>1000</counter>
* this function is currently not used in the main program.
*/
protected String getNextId() throws Exception
{
String incQuery = " update "
+ " let $c := input()/counter/text() "
+ " do replace $c with ( $c + 1 ) ";
Tamino XML-Datenbank
}
Technologie Memo
Arno Schmidhauser
/*
* Copyright (c) 2002-2004 SOFTWARE AG, All Rights Reserved.
*/
12 Beispiel DOM-Anbindung
}
}
catch ( Exception e ) {
e.printStackTrace();
}
}
docman.disconnect();
// save student to database
Document confirmation = docman.saveStudent( student );
System.out.println( "student updated." );
15
// modify student record: add new course and ects points.
// instead of this code a generic graphical xml editor might be called
Element faecher = (Element)(student.getElementsByTagName( "faecher" ).item(0));
Element fach = doc.createElement( "fach" );
faecher.appendChild( fach );
Element titel = doc.createElement( "titel" );
fach.appendChild( titel );
titel.appendChild( doc.createTextNode( fachArg ) );
Element ects = doc.createElement( "ects" );
fach.appendChild( ects );
ects.appendChild( doc.createTextNode( punkteArg ) );
// add course record for each student
for( int i = 0; i < studList.getLength(); i++ ) {
Element student = (Element)studList.item(i);
NodeList studList = doc.getElementsByTagName( "student" );
Tamino XML-Datenbank
Arno Schmidhauser
com.softwareag.tamino.db.api.accessor.TAccessLocation;
com.softwareag.tamino.db.api.accessor.TAccessorException;
com.softwareag.tamino.db.api.accessor.TDeleteException;
com.softwareag.tamino.db.api.accessor.TInsertException;
com.softwareag.tamino.db.api.accessor.TQuery;
com.softwareag.tamino.db.api.accessor.TQueryException;
com.softwareag.tamino.db.api.accessor.TSystemAccessor;
com.softwareag.tamino.db.api.accessor.TXMLObjectAccessor;
com.softwareag.tamino.db.api.common.TAccessFailureMessage;
com.softwareag.tamino.db.api.common.TException;
com.softwareag.tamino.db.api.connection.TConnection;
com.softwareag.tamino.db.api.connection.TConnectionFactory;
com.softwareag.tamino.db.api.connection.TLockMode;
Technologie Memo
import
import
import
import
import
import
import
import
import
import
import
import
import
16
/*
|| Example for the Tamino API for Java.
||
|| Assumes that there is a Tamino database called "mydb".
|| The example simply uses the default collection ino:etc.
|| This collection should only be used for examples/test code.
|| It shouldn't generally be used for real applications.
||
|| The example does the following:
||
|| establishes a connection to the Tamino database
|| obtains a system accessor and prints out some system information
|| obtains an XML accessor
|| reads some XML documents from files and inserts them into the collection ino:etc
|| creates two queries, one for all person documents and one for all persons named "Atkins"
|| queries all persons and list them
|| use a boolean query to check if any person named "Atkins" is stored in the database
|| if such persons are found, delete them
|| queries again all persons and list them
|| delete the rest of the persons
|| closes the connection
*/
package com.softwareag.tamino.db.api.examples.person;
Tamino XML-Datenbank
com.softwareag.tamino.db.api.connection.TLocalTransaction;
com.softwareag.tamino.db.api.io.TStreamWriteException;
com.softwareag.tamino.db.api.objectModel.TXMLObject;
com.softwareag.tamino.db.api.objectModel.TXMLObjectIterator;
com.softwareag.tamino.db.api.objectModel.TXMLObjectModel;
com.softwareag.tamino.db.api.objectModel.dom4j.TDOM4JObjectModel;
com.softwareag.tamino.db.api.response.TResponse;
java.io.FileNotFoundException;
java.io.InputStream;
java.util.List;
org.dom4j.Element;
Technologie Memo
Arno Schmidhauser
17
// Helpermethod to get the text of a given tagname from a DOM4J tree
private static String getDOM4JElementTextByTagName(Element element, String tagname) {
List list = element.elements( tagname );
Element elem = (Element)list.get(0);
return elem.node(0).getStringValue();
}
}
if (!systemaccessor.isServerAlive()) {
return false;
} else {
System.out.println( " server is alive" );
System.out.println( "\nHere is some systeminformation" );
System.out.println( "------------------------------\n" );
System.out.println( "The Tamino server hosting " + DATABASE_URI + " is version "
+ systemaccessor.getServerVersion() );
System.out.println( "(Server API version: " + systemaccessor.getAPIVersion()
+ ", Tamino API for Java version: " + systemaccessor.getAPIVersion() + ")\n" );
return true;
}
// use a sytem accessor, to check, if the database is alive and print some system information to stdout
protected static boolean checkServerAndPrintSystemInformation(TConnection connection) throws TAccessorException {
// Obtain the TSystemAccesor
TSystemAccessor systemaccessor = connection.newSystemAccessor();
public class ProcessPersonsDOM4J {
import
import
import
import
import
import
import
import
import
import
import
Tamino XML-Datenbank
Technologie Memo
Arno Schmidhauser
18
}
catch (TInsertException insertException) {
System.out.print( "\nCan't insert: " );
printPerson( xmlObject );
System.out.println( " Reason: " + insertException.getAccessFailureException().getMessageLine() + "\n" );
}
return xmlObject;
System.out.print( " Inserted: " );
printPerson(xmlObject);
try {
// Invoke the insert operation and obtain the response.
TResponse response = accessor.insert( xmlObject );
// Read a document out of the classpath and insert it into the database.
InputStream myInputStream = (new ProcessPersonsDOM4J()).getClass().getResourceAsStream( filename );
xmlObject.readFrom( myInputStream );
// read a given filename into an TXMLObject, store it in the database and print the person
protected static TXMLObject performInsertPersonFromFile(TXMLObjectAccessor accessor, String filename) throws TException, FileNotFoundException {
// Instantiate an empty TXMLObject instance related to the DOM4J object model.
TXMLObject xmlObject = TXMLObject.newInstance( TDOM4JObjectModel.getInstance() );
}
System.out.print( " (" );
System.out.print( "ino:id=\"" + xmlObject.getId() +"\" " );
System.out.print( "collection=\"" + xmlObject.getCollection() +"\" " );
System.out.print( "doctype=\"" + xmlObject.getDoctype() +"\" " );
System.out.println( ")" );
String surname = getDOM4JElementTextByTagName(e, "surname");
String firstname= getDOM4JElementTextByTagName(e, "firstname");
System.out.print( surname + ", " + firstname);
// Obtain the DOM4J root element
Element e = (Element)xmlObject.getElement();
// List some data about a person to stdout
private static void printPerson(TXMLObject xmlObject) throws TStreamWriteException {
Tamino XML-Datenbank
{
Technologie Memo
Arno Schmidhauser
19
// delete all documents for a given query with a given accessor
protected static void performDelete(TXMLObjectAccessor accessor, TQuery query) throws TException
{
// perform a query and list all persons, which are returned
protected static void performQueryAndListPersons(TXMLObjectAccessor accessor, TQuery query) throws TException
// Now lets make the query
try {
TResponse response = accessor.query( query );
TXMLObjectIterator iterator = response.getXMLObjectIterator();
System.out.print( "The query \"" + query + "\" returns " );
if (!iterator.hasNext()) {
System.out.println( "no documents!" );
} else {
System.out.println( performCountQuery( accessor, query ) + " documents, which are:" );
while (iterator.hasNext()) {
TXMLObject xmlObject = iterator.next();
System.out.print( " " );
printPerson(xmlObject);
}
}
} catch (TQueryException queryException) {
showAccessFailure( queryException );
throw queryException;
}
}
// take a given query, put the count() function around and return the result as String
private static String performCountQuery(TXMLObjectAccessor accessor, TQuery query) throws TException
try {
// Build a new query string
TQuery countquery = TQuery.newInstance( "count(" + query.getExpression() + ")" );
return accessor.query( countquery ).getQueryContentAsString();
}
catch (TQueryException queryException) {
showAccessFailure( queryException );
throw queryException;
}
}
}
Tamino XML-Datenbank
{
Technologie Memo
Arno Schmidhauser
// Instantiate the specific TDOM4JObjectModel
TXMLObjectModel dom4jObjectModel = TDOM4JObjectModel.getInstance();
20
// Obtain the connection factory
TConnectionFactory connectionFactory = TConnectionFactory.getInstance();
// Obtain the connection to the database
TConnection connection = connectionFactory.newConnection( DATABASE_URI );
TLocalTransaction myTransaction=connection.useLocalTransactionMode();
connection.setLockMode(TLockMode.SHARED);
// Check if the connection is available and print out some system information
if ( !checkServerAndPrintSystemInformation( connection ) )
return;
public static void main(String[] args) throws TException {
//TTrace.setActiveTrace(true);
// Print out a program header to stdout
System.out.println( "\nProcessPersonsDOM4J sample programm" );
System.out.println( "==============================" );
System.out.print( "Connecting to Tamino database " + DATABASE_URI + ", ..." );
// Show the reason for the access failure.
private static void showAccessFailure(TAccessorException accessorException) {
// Obtain an access failure message telling the exact reason if Tamino request failed.
TAccessFailureMessage accessFailure = accessorException.getAccessFailureException();
if ( accessFailure != null )
System.out.println( "Access failed with:" + accessFailure );
else
System.out.println( "Access failed:" + accessorException.getMessage() );
}
}
// Finally, lets delete the document again
try {
TResponse response = accessor.delete( query );
System.out.println("\nDeleted all documents for query \"" + query + "\"");
}
catch (TDeleteException deleteException) {
showAccessFailure( deleteException );
throw deleteException;
}
Tamino XML-Datenbank
Technologie Memo
Arno Schmidhauser
// Do some processing, if persons named "Atkins" are stored
21
// Create a boolean query and check if persons named "Atkins" are stored
TQuery queryAtkins = TQuery.newInstance( "//surname='Atkins'" );
String queryAtkinsResult = accessor.query( queryAtkins ).getQueryContentAsString();
System.out.println( "\nThe query \"" + queryAtkins + "\" returns \"" + queryAtkinsResult + "\"" );
boolean AtkinsAvailable = new Boolean( queryAtkinsResult ).booleanValue();
System.out.println("");
// Initiate a query to count and list all instances of a certain Doctype
performQueryAndListPersons( accessor, queryall );
// Build a query to reference documents of doctype "person" with surname = "Atkins"
TQuery querysome = TQuery.newInstance( xmlObject.getDoctype() + "[//surname='Atkins']" );
// Build a query to reference all documents of doctype "person"
TQuery queryall = TQuery.newInstance( xmlObject.getDoctype() );
performInsertPersonFromFile( accessor, "person1.xml" );
performInsertPersonFromFile( accessor, "person2.xml" );
performInsertPersonFromFile( accessor, "person3.xml" );
performInsertPersonFromFile( accessor, "person4.xml" );
xmlObject = performInsertPersonFromFile( accessor, "person5.xml" );
// read person documents from files and insert them into the "people" collection
System.out.println( "Reading documents from file and insert into database\n" );
try {
// Instantiate an empty TXMLObject instance related to the DOM4J object model.
TXMLObject xmlObject = TXMLObject.newInstance( TDOM4JObjectModel.getInstance() );
// Print header for database operations
System.out.println( "Insert and query and delete in default collection \"ino:etc\"" );
System.out.println( "-----------------------------------------------------------\n" );
// Do the object model registration.
TXMLObjectModel.register( dom4jObjectModel );
// Obtain a TXMLObjectAccessor to the "ino:etc" collection with an underyling DOM4J object model
TXMLObjectAccessor accessor =
connection.newXMLObjectAccessor( TAccessLocation.newInstance( "ino:etc" ) , dom4jObjectModel );
Tamino XML-Datenbank
Technologie Memo
}
Arno Schmidhauser
22
// Constant for the database URI. Please edit to use your uri of interest.
private final static String DATABASE_URI = "http://localhost/tamino/mydb";
}
}
catch (TException taminoException) {
if (myTransaction != null) myTransaction.rollback();
taminoException.printStackTrace();
}
catch (FileNotFoundException filenotfoundException) {
filenotfoundException.printStackTrace();
}
finally {
// Close the connection.
connection.close();
}
// Initiate the removal
performDelete( accessor, queryall );
}
System.out.println("");
// Initiate a query to count and list all instances of a certain Doctype
performQueryAndListPersons( accessor, queryall );
myTransaction.commit();
// Initiate the removal of all "Atkins"
performDelete( accessor, querysome );
if (AtkinsAvailable) {
System.out.println("So list and then delete all \"Atkins\" documents\n");
// Initiate a query to count and list some instances of a certain Doctype
performQueryAndListPersons( accessor, querysome);
Tamino XML-Datenbank
Herunterladen