<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document>
   <head>
      <pagetitle>Scriptum zur Vorlesung Datenbank-Anwendungen</pagetitle>
      <metatags description="Scriptum zur Vorlesung Datenbank-Anwendungen" keywords="Scriptum Datenbank-Anwendungen, Vorlesung, JDBC, SQLJ, EJB, JDO, EJB, PHP, XML, XSD, Web Services" url="http://www.jeckle.de/vorlesung/db-anwendungen/script.html">
         <nocache/>
         <robots revisit-after="10 days"/>
         <css/>
      </metatags>
   </head>
   <body>
      <navigation titleimage="dbanwendungen.png">
         <navup reference="Vorlesung DB-Anwendungen" destinationuri="index.html"/>
         <navseparator/>
         <navpage reference="1 Schnittstellen und Einbettungstechniken" destinationuri="#chap1"/>
         <navpage reference="1.1 Java Database Connectivity" destinationuri="#jdbc"/>
         <navpage reference="1.2 Enterprise Java Beans" destinationuri="#ejb"/>
         <navpage reference="1.3 Java Data Objects" destinationuri="#jdo"/>
         <navpage reference="2 Architekturmuster and Umsetzungstechniken" destinationuri="#chap2"/>
         <navpage reference="2.1 Domänenlogik" destinationuri="#domlog"/>
         <navpage reference="2.2 Datenzugriff" destinationuri="#dbacc"/>
         <navpage reference="2.3 Objekt-Relational-Abbildung und -Interoperabilität" destinationuri="#or"/>
         <navpage reference="3 Konnektivität und Offline-Techniken" destinationuri="chap3"/>
         <navpage reference="3.1 XML-Strukturen" destinationuri="#xmlstr"/>
         <navpage reference="3.2 XML-Schema" destinationuri="#xsd"/>
         <navpage reference="3.3 XSL-Transformationen" destinationuri="#xslt"/>
         <navpage reference="3.4 XML-Programmierschnittstellen" destinationuri="#xmlapi"/>
         <navpage reference="3.5 XML und Datenbanken" destinationuri="#xmldb"/>
         <navpage reference="3.6 Web Services" destinationuri="#ws"/>
      </navigation>
      <topic name="chap1">1 Zugriffsschnittstellen</topic>
      <p>Dieses Kapitel führt in drei Zugriffsschnitstellen auf Datenbanken und persistente Objektspeicher ein.
        Die Darstellung skizziert daher zunächst die auf das relationale Speicherungs- und Zugriffsparadigma
        ausgelegte JDBC-Schnittstelle.<br/>
        Davon ausgehend wird die Kapselung von JDBC-basierter Persistenzlogik durch
        Enterprise Java Beans entwickelt. Hierbei steht die Ausprägungsform der bean managed persistence im
        Vordergrund, da sie die weitestgehenden Eingriffsmöglichkeiten für den Programmierer bietet.<br/>
        Abschließend wird mit den <em>Java Data Objects</em> ein jüngerer Ansatz zur Realisierung transparenter
        Speicherung eingeführt, der gleichzeitig verschiedenste Persistenzdienstleiter unterstützt.</p>
      <subtopic name="jdbc">1.1 Java Database Connectivity</subtopic>
      <span xml:base="file:/I:/development/vorlesung/sharedScriptParts/jdbc-dba.xml">
         <subsubtopic>Motivation</subsubtopic>
         <p>Häufig besteht der Wunsch oder die Notwendigkeit, auf
        bereits vorliegende Datenbestände, die durch ein
        Datenbankmanagementsystem (DBMS) verwaltet werden, in einer Applikationsprogrammiersprache
        zuzugreifen. Dabei soll die Anbindung der benötigten Datenquelle
        nicht problemspezifisch wieder und wieder neu entwickelt
        werden, sondern sollte sich auf ähnliche
        Datenanbindungsprobleme übertragen lassen.<br/>
        Vor diesem Hintergrund liegt es nahe, sich an den Typen der
        verfügbaren und kommerziell bedeutsamen
        DBMS zu orientieren und
        herstellerspezifische Entwicklungen außer Acht zu lassen.
        Gleichzeitig offenbaren sich hierbei
        Standardisierungsbemühungen wie die Sprache <em>SQL</em> zum Zugriff
        auf relationale DBMS als lohnenswerter Ansatz der
        Etablierung einer generischen und übertragbaren
        Schnittstelle.</p>
         <p>Die Idee zur Schaffung einer solchen generischen
        Schnittstelle für den Zugriff auf relationale DBMS geht
        zurück auf eine Initiative der <em>SQL Access Group</em>,
        welche später in der Vereinigung mit der
        <em>X/Open</em> Group aufging, die zwischenzeitlich in
        <em>
               <a href="http://www.opengroup.org">Open Group</a>
            </em>
        umbenannt wurde. Das dort konzipierte programmiersprachenunabhängige <em>
               <keyword>SQL Call Level
        Interface</keyword>
            </em> (<keyword>SQL/CLI</keyword>) konnte sich dank der Umsetzung
        unter dem Namen <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_odbc.asp">
               <keyword>Open
        Database Connectivity</keyword>
            </a> (<keyword>ODBC</keyword>) durch die Firma
        <name>Microsoft</name>
        und die parallel erfolgte internationale Normierung unter
        dem Titel <em>
               <a href="http://www.iso.ch/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=30609&amp;ICS1=35&amp;ICS2=60&amp;ICS3">SQL/CLI</a>
            </em>
        breit am Markt etablieren.</p>
         <p>Die für die Programmiersprache <name>Java</name>
        adaptierte Variante des Zugriffs auf relationale DBMS wird
        durch <name>SUN Microsystems</name> unter dem Namen <a href="http://java.sun.com/producs/jdbc">
               <em>
                  <keyword>Java Database
        Connectivity</keyword>
               </em>
            </a> (<keyword>JDBC</keyword>)
        propagiert und stellt eine auf ODBC konzeptionell aufbauende und auf die spezifischen Bedürfnisse dieser
        Applikationsprogrammiersprache optimierte Untermenge des
        SQL/CLI-Standards dar.</p>
         <subsubtopic>Konzept und Grundidee</subsubtopic>
         <p>Von den Vorgängeransätzen übernommene Grundidee der
        Schnittstelle ist es den physischen Zugriff auf das
        Datenbankmanagementsystem durch eine von der Applikation
        spearierte wiederverwendbare Softwarekomponente, den sog.
        <em>
               <keyword>JDBC-Treiber</keyword>
            </em>, abzuwickeln.</p>
         <p>Dieser Treiber vermittelt zwischen der Javaapplikation
        und dem verwendeten DBMS. Hierbei muß für jedes DBMS ein
        auf es abgestimmter JDBC-Treiber verwendet werden, da
        lediglich die Schnittstelle zur Applikation, nicht jedoch
        die zum DBMS, standardisiert ist.</p>
         <p>Diesem Treiber obliegt die Abwicklung der gesamten
        Kommunikationsvorgänge mit dem DBMS. Er setzt jedoch
        selbst keine datenbankspezifischen Funktionalitäten, wie
        Syntax- oder Plausibilitätsprüfungen der übermittelten
        Kommandos um. Etwaige Fehlerprüfungen können, ebenso wie Anfrageoptimierungen,
        daher erst seitens des DBMS vorgenommen werden.<br/>
        Der Vorteil dieses Vorgehens liegt in der Generizität des
        JDBC-Treibers. Er kann ohne aufwendige Logikanteile als
        reine uninterpretierende Vermittlungsschicht zwischen Applikation
        und DBMS umgesetzt werden, wodurch schlanke Implementierungen ermöglicht werden.</p>
         <p>Die <a href="http://java.sun.com/products/jdbc/download.html#corespec30">JDBC-Spezifikation</a>
        detailliert den Treiberbegriff zusätzlich hinsichtlich der
        gewählten technischen Umsetzung aus. So werden die vier in
        <illustrationLink ref="JDBCDriverTypes"/> dargestellten Treibertypen gemäß ihrer
        Charakteristika beschrieben und unterschieden.</p>
         <illustration id="JDBCDriverTypes" width="650" caption="JDBC-Treibertypen" gfx="ebe/JDBCdrivers.gif"/>
         <p>
            <a name="typ1drv">Die</a> historisch älteste Variante bildet der <b>
               <name>
                  <keyword>Typ 1
        Treiber</keyword>
               </name>
            </b>. Strenggenommen verkörpert er selbst keinen
        Datenbanktreiber, sondern lediglich eine Umsetzungsschicht
        die einem existierenden ODBC-Treiber vorgeschaltet
        wird.<br/>
        Die Abbildung belegt diesen Treibertyp daher mit dem
        Begriff <em>JDBC-ODBC-Bridge</em>, da er lediglich den
        Brückenschlag zwischen den beiden Standards vornimmt und
        sich in der konkreten Anwendung auf die Umsetzung
        zwischen den beiden Protokollen beschränkt, ohne realen
        Zugriff auf die Datenbank zu erhalten.<br/>
        Dieser ist dem ODBC-Treiber vorbehalten, der im allgemeinen Falle mit einer weiteren Umsetzungsstufe
        kommuniziert, welche die generischen ODBC-Aufrufe in konkrete DBMS-spezifische wandelt.<br/>
        Während sowohl der JDBC-ODBC-Brückentreiber als auch der
        ODBC-Treiber selbst für verschiedene DBMS verwendet werden
        können, muß für jedes konkrete DBMS eine
        herstellerspezifische, d.h. an das verwendete DBMS
        angepaßte, Bibliothek vorliegen.</p>
         <p>Für den Fall eines <b>
               <name>
                  <keyword>Typ 2 Treiber</keyword>
               </name>
            </b>s entfällt
        diese durch ODBC geschaffene zusätzliche Indirektionsstufe
        zugunsten der Adaption der Konversionskomponente, welcher
        die Wandlung der Aufrufe in das DBMS-native Protokoll
        obliegt, an das JDBC-Protokoll und ihrer Integration in den JDBC-Treiber
        selbst.<br/>
        Die Natur der Kommunikation des Java-Anteils des Treibers mit den
        Nativen ist im Rahmen der durch die JDBC-Spezifikation
        gegebenen Definition nicht festgelegt.<br/>
        Durch die integration der DBMS-nativen Treiberanteile in den JDBC-Treiber muß dieser
        für jedes anzusprechende DBMS neu erstellt werden. Eine Wiederverwendung der JDBC-spezifischen
        Anteile, die für die Clientkommunikation eingesetzt werden, kann hierbei nicht erfolgen.</p>
         <p>Der Fall der (partiellen) Konkretisierung dieser
        Kommunikationsbeziehung zu einem beliebigen <em>DBMS-neutralen
        Protokoll</em> wird durch einen <b>
               <name>
                  <keyword>Typ 3 Treiber</keyword>
               </name>
            </b>
        aufgegriffen.<br/>
        Hier wird die DBMS-spezifische Komponente (in der
        Abbildung grau dargestellt) als vom JDBC-Treiber
        separiertes Modul aufgefaßt, daß mit diesem mittels eines
        festgelegten neutralen Protokolls kommuniziert.<br/>
        Durch diese Separierung, die auch durch Installation auf physisch getrennten
        Maschinen --- der DBMS-spezifische Anteil könnte beispielsweise auf einem Middleware-Server untergebracht werden --- fundiert werden kann, gelingt die Wiederverwendung des JDBC-Treiberanteils, der
        mit verschiedenen DBMS-spezifischen Bibliotheken über das gewählte Protokoll kommunizieren kann.</p>
         <p>Der <b>
               <name>
                  <keyword>Typ 4 Treiber</keyword>
               </name>
            </b> stellt die letzte durch
        die JDBC-Spezifikation vorgesehene Ausprägung dar. Er
        konzipiert eine vollständig in Java implementierte
        Zugriffsschicht, die in sich geschlossen ist. Sie besitzt
        daher lediglich die notwendige JDBC-Schnittstelle zur
        Kommunikation mit der Java-Applikation und eine
        DBMS-Spezifische zum Zugriff auf die Datenquelle.<br/>
        Die Vorteile dieser Architekturvariante liegen in ihrer
        Portabilität und den geringen Installations und
        Wartungsaufwänden, die aus der Reduktion der
        Kommunikationsbeziehungen resultieren. So kann ein solcher
        Treiber durch einfache Integration in die Java-Applikation
        verwendet werden und bedarf keiner Installationen oder
        Modifikationen an der verwendeten Ausführungsumgebung.<br/>
        Gleichzeitig offenbart sich diese Lösung jedoch als
        technisch aufwendig in der Umsetzung, sobald
        DBMS verschiedener Hersteller angesprochen werden sollen,
        da die JDBC-Anteile des Treibers nicht separat
        wiederverwendet werden können.</p>
         <p>Hinsichtlich des Laufzeitverhaltens zeigt sich deutlich
        die Schwäche der <name>Typ 1 Treiber</name>, welche in der
        inhärent notwendigen Doppelkonversion (JDBC zu ODBC und
        ODBC zu nativem Aufruf) begründet liegt. Daher sind
        Treiber dieses Typs als Übergangserscheinung hin zu
        <gerquot>echten</gerquot> JDBC-Treibern, d.h. Treibern der
        restlichen Typen, anzusehen und sollten in
        Produktivumgebungen nicht eingesetzt werden.<br/>
        Die Vorteile der <name>Typ 2</name> und <name>3 Treiber</name> seitens der
        Ausführungsgeschwindigkeit liegen in den nativen
        Codeanteilen begründet, welche für das jeweilige verwendete
        DBMS optimiert werden können.<br/>
        Zwar spricht der leichte Installations- und
        Adminstrationsaufwand eindeutig für <name>Typ 4
        Treiber</name>, jedoch fallen diese in ihrer
        Leistungsfähigkeit durch die ausschließliche Verwendung
        der Programmiersprache Java teilweise deutlich hinter
        Treiber des Typs 2 und 3, mit unter sogar hinter solche des Typs 1,
        zurück. Sie verkörpern jedoch den aus konzeptioneller
        Sicht zu bevorzugenden Ansatz hinsichtlich Portabilität
        und Vergleichbarkeit der erzielten quantitativen Ergebnisse.<br/>
        Typischerweise kommen im
        produktiven Einsatz jedoch Treiber der Typen 2 und 4 zum Einsatz,
        die entweder durch den Hersteller des DBMS mitgeliefert werden (Typ 2) oder
        auf der Basis publizierter Schnittstellen plattformunabhängig
        für genau ein spezifisches DBMS entwickelt wurden (Typ 4).
        </p>
         <p>Generell formuliert das JDBC-Konzept auf dieser Ebene noch
        keine Einschränkung hinsichtlich der unterstützten
        DBMS-Typen und ist generell auf verschiedenste
        Datenquellen anwendbar. Durch die Struktur des API und die
        verfügbaren Treiber kristallisieren sich jedoch
        relationale DBMS als Hauptanwendungsgebiet dieser
        Zugriffsschnittstelle heraus.</p>
         <p>Im folgenden wird die Verwendung des <name>Typ 4
        Treibers</name> <name>
               <a href="http://www.mysql.com/products/connector-j/">Connector/J</a>
            </name>
        im Zusammenspiel mit dem RDBMS <name>
               <em>MySQL</em>
            </name>
        betrachtet.</p>
         <p>Die Beispiele basieren auf einer Demodatenbank, deren
        Struktur und Inhalte nachfolgend angegeben sind.</p>
         <p>
            <a name="TabEmployee">
               <em>Die Tabelle <code>EMPLOYEE</code>
               </em>
            </a>
         </p>
         <code>
            <pre>+----------+-------+---------+-----------+------------+--------------------------+------+----------+-----------+------+
| FNAME    | MINIT | LNAME   | SSN       | BDATE      | ADDRESS                  | SEX  | SALARY   | SUPERSSN  | DNO  |
+----------+-------+---------+-----------+------------+--------------------------+------+----------+-----------+------+
| John     | B     | Smith   | 123456789 | 1965-01-09 | 731 Fondren, Houston, TX | M    | 30000.00 | 333445555 |    5 |
| Franklin | T     | Wong    | 333445555 | 1955-12-08 | 638 Voss, Houston, TX    | M    | 40000.00 | 888665555 |    5 |
| Joyce    | A     | English | 453453453 | 1972-07-31 | 5631 Rice, Houston, TX   | F    | 25000.00 | 333445555 |    5 |
| Ramesh   | K     | Narayan | 666884444 | 1962-09-15 | 975 Fire Oak, Humble, TX | M    | 38000.00 | 333445555 |    5 |
| James    | E     | Borg    | 888665555 | 1937-11-10 | 450 Stone, Houston, TX   | M    | 55000.00 |      NULL |    1 |
| Jennifer | S     | Wallace | 987654321 | 1941-06-20 | 291 Berry, Bellaire, TX  | F    | 43000.00 | 888665555 |    4 |
| Ahmad    | V     | Jabbar  | 987987987 | 1969-03-29 | 980 Dallas, Houston, TX  | M    | 25000.00 | 987654321 |    4 |
| Alicia   | J     | Zelaya  | 999887777 | 1968-07-19 | 3321 Castle, Spring, TX  | F    | 25000.00 | 987654321 |    4 |
+----------+-------+---------+-----------+------------+--------------------------+------+----------+-----------+------+

</pre>
         </code>
         <subsubtopic>Umsetzung in der Java-API</subsubtopic>
         <p>Das Klassendiagramm der <illustrationLink ref="JDBCJava"/> zeigt die zentralen Klassen des Paketes
        <a fixedType="JDK14" offset="java/sql/package-frame.html" keyword="yes">java.sql</a>.<br/>
        Auffallend ist, daß alle Elemente des dargestellten Pakets
        -- abgesehen von den definierten Exceptionklassen -- als
        Schnittstellen ausgelegt sind. Durch diese Mimik wird die
        Organisation der JDBC-Schnittstelle deutlich. Die API legt
        lediglich das Verhalten hinsichtlich seiner Semantik und
        die Einzeloperationen durch Definition ihrer Parameter
        fest, die konkrete DBMS-spezifische Implementierung dieser
        Operationen wird durch den JDBC-Treiber bereitgestellt.</p>
         <p>Zentrale Klasse der JDBC-API ist die Schnittstelle <a fixedType="JDK14" offset="java/sql/Connection.html" keyword="yes">Connection</a>. Sie bildet die
        Kommunikationsverbindungen zum DBMS ab und bietet
        notwendige Verwaltungsoperationen.<br/>
        Hierunter fallen insbesondere auch die Aufrufe zur Transaktionssteuerung.</p>
         <p>Die Schnittstelle <a fixedType="JDK14" offset="java/sql/Statement.html" keyword="yes">Statement</a> realisiert genau eine aus
        Javasicht atomare Datenbankaktion. Diese muß hierbei aus
        minimal einem Aufruf an das DBMS bestehen, kann aber
        eine Reihe separater Aufrufe zu einem <em>Batch</em>
        bündeln.<br/>
        Als Sonderform sieht die API die Spezialisierung <a fixedType="JDK14" offset="java/sql/PreparedStatement.html" keyword="yes">PreparedStatement</a>
        vor, die es gestattet, parametrisierte Anfragen zwischenzuspeichern, die nach Belegung der Parameterfelder an das DBMS übergeben
        werden. Hierdurch wird ein einfacher Mechanismus zur Wiederverwendung von DBMS-Aufrufen etabliert.</p>
         <p>Liefert eine DBMS-Anfrage Ergebnistupel, so werden
        diese konform zur Schnittstelle <a fixedType="JDK14" offset="java/sql/ResultSet.html" keyword="yes">ResultSet</a> verwaltet. Diese Schnittstelle
        erlaubt die lesende Traversierung der vom DBMS gelieferten
        Tupel ebenso wie ihre Aktualisierung im Hauptspeicher und
        das anschließende Zurückschreiben in die Datenbank.<br/>
        Die in der Abbildung nur durch <em>getXXX</em> und <em>updateXXX</em> angedeuteten
        Operationen existieren in Ausprägungen für alle unterstützten Datentypen, wobei <em>XXX</em> den Namen
        des Typs bezeichnet.</p>
         <p>Ferner definiert die API mit <a fixedType="JDK14" offset="java/sql/SQLWarning.html" keyword="yes">SQLWarning</a> eine Ausnahme zur Behandlung
        auftretender Fehlersituationen sowie eine Reihe weiterer,
        in der <illustrationLink ref="JDBCJava"/> nicht
        dargestellter Klassen wie beispielsweise verschiedene
        Datentypen.</p>
         <p>Die Klasse <a fixedType="JDKcurrent" offset="java/sql/SQLException.html" keyword="yes">SQLException</a>
		  bietet durch ihre Methoden <a fixedType="JDKcurrent" offset="java/sql/SQLException.html#getErrorCode()" keyword="yes">getErrorCode</a> und <a fixedType="JDKcurrent" offset="java/sql/SQLException.html#getSQLState()" keyword="yes">getSQLState</a> Möglichkeiten an um die nähere Ursache eines datenbankseitigen Fehlers zu ermitteln.<br/>
		  Zusätzlich gestatten Objekte dieses Ausnahmetyps die Verschachtelung von Ausnahmen, d.h. die rekursive Einbettung eines Ausnahmeereignisobjekts in ein bestehendes. Auf diesem Wege können aufgetretene Fehler durch mehrere Ausnahmeobjekte näher spezifiziert werden.<br/>
Beispiel <scriptRef type="example" name="SQLEx1"/> zeigt die Abfrage von Details der empfangenen und aller eingebetteten Ausnahmeereignisobjekte mittels der durch die JDBC-API vorgesehenen Methoden.</p>
         <scriptElement type="example" name="SQLEx1" title="Ermittlung von Fehlerdetails" filename="jdbcSQLException1.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/jdbcSQLException1.java"/>
         </scriptElement>
         <p>Mit der Version 1.4 der Java-Standard-Edition wurde die zuvor nur in der JDBC-API zur Verfügung stehende Möglichkeit zur Schachtelung von Ausnahmeereignissen auch für beliebige Ausnahmeereignisobjekte des Typs <a fixedType="JDKcurrent" offset="java/lang/Throwable.html" keyword="yes">Throwable</a> definiert.<br/>
Anders als die JDBC-API sieht die generische Lösung jedoch die Nutzung der Methode <a fixedType="JDKcurrent" offset="java/lang/Throwable.html#getCause()" keyword="yes">getCause</a> zur Extraktion der eingebetteten Ausnahmeereignisobjekte vor.<br/>
Der Code des Beispiels <scriptRef type="example" name="SQLEx2"/> spiegelt daher die Standard-API-konforme Realisierung wieder. Zusätzlich wendet die Lösung die Standard-Methode <a fixedType="JDKcurrent" offset="java/lang/Throwable.html#getMessage()" keyword="yes">getMessage</a> zur Ermittlung der deskriptiven Fehlerbeschreibung an.</p>
         <scriptElement type="example" name="SQLEx2" title="Standard-API-konforme Ermittlung von Fehlerdetails" filename="jdbcSQLException2.java.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/jdbcSQLException2.java"/>
         </scriptElement>
         <illustration id="JDBCJava" width="650" caption="Zentrale JDBC-Klassen der Java-API" gfx="JDBCJava.gif"/>
         <subsubtopic>Zugriff auf die Datenbank</subsubtopic>
         <p>Beispiel <scriptRef type="example" name="connect"/>
        zeigt den Ablauf zur Aufnahme einer Verbindung mit der
        Datenbank <code>jdbctest</code> auf dem lokalen Rechner
        (<code>localhost</code>).</p>
         <p>Zunächst muß die Klasse des gewählten JDBC-Treibers (im
        Beispiel <code>com.mysql.jdbc.Driver</code> vor ihrer Verwendung
        geladen werden. Dies geschieht durch den Aufruf der statischen Methode <a fixedType="JDK14" offset="java/lang/Class.html#forName(java.lang.String)" keyword="yes">forName</a> auf der Klasse <a fixedType="JDK14" offset="java/lang/Class.html" keyword="yes">Class</a>.<br/>
        Der zu ladende Treiber muß hierbei die
        JDBC-Schnittstellenklasse <a fixedType="JDK14" offset="java/sql/Driver.html" keyword="yes">Driver</a> implementieren um später durch
        die JDBC-API verwendet werden zu können.<br/>
        Gleichzeitig mit dem dynamischen Ladevorgang erfolgt die Registrierung des
        Treibers beim JDBC-<a fixedType="JDK14" offset="java/sql/DriverManager.html" keyword="yes">DriverManager</a>,
        der die Verwaltung der geladenen DB-Treiber übernimmt.</p>
         <p>Nach dem erfolgreichen Laden des Treibers wird durch den Aufruf von <a fixedType="JDK14" offset="java/sql/DriverManager.html#getConnection(java.lang.String, java.lang.String,         java.lang.String)" keyword="yes">getConnection</a> (Zeile
        16) die Verbindung zur Datenbank hergestellt. Die
        anzusprechende Datenbank wird hierbei durch eine URI der
        Form
        <code>jdbc:mysql://<em>DB-Server</em>/<em>DB-Name</em>
            </code>
        repräsentiert (Zeile 17). Zusätzlich können ein zur
        Anmeldung am DB-System benötiger Benutzer (Zeile 18) und sein Paßwort (Zeile 19)
        übergeben werden.</p>
         <scriptElement type="example" name="connect" title="Aufbau einer Datenbankverbindung" filename="JDBCConnect.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCConnect.java"/>
         </scriptElement>
         <p>Zusätzlich stellen die Klassen <code>Driver</code> und
        <code>DriverManager</code> die Möglichkeit der Abfrage von
        verbindungsunabhängigen Verwaltungsinformationen zur
        Verfügung.</p>
         <scriptElement type="example" name="driverInfo" title="Ermittlung von Informationen über Treiber und Treibermanager" filename="JDBCDriver.java" resultfile="JDBCDriver.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCDriver.java"/>
         </scriptElement>
         <p>Beispiel <scriptRef type="example" name="driverInfo"/>
        zeigt die Ermittlung des durch den
        <code>DriverManager</code> für alle durch ihn verwalteten
        Treiber global definierten Login Timouts, der angibt
        wie lange beim Anmeldevorgang an der Datenbank auf eine
        Rückmeldung gewartet wird.<br/>
        Zusätzlich werden für alle verwalteten Treiber
        der Klassenname sowie Daten zur Version und zum Stand der
        JDBC-Unterstützung ermittelt und ausgegeben.<br/>
        Der JDBC-Unterstützungsstand gibt an, ob ein gegebener
        Treiber die Konformitätstests der Firma SUN bestanden hat.
        Voraussetzung hierfür ist u.a. die vollständige
        Unterstützung des SQL 92-Standards (entry level).<br/>
        Diese Interpreatation von Spezifikationskonformität
        verwundert etwas, da alle JDBC-Treiber mit Ausnahme der
        inhärent DB-neutralen <name>
               <a href="#typ1drv">Typ 1
        Treiber</a>
            </name> DBMS-spezifisch realisiert sind. Aus
        diesem Grunde bewertet der Konformitätstest vielmehr den
        Umsetzungsgrad des SQL-Standards in dem via JDBC genutzten
        DBMS als die Güte des JDBC-Treibers selbst.</p>
         <p>Seit der JDBC-Schnittstellenversion 2 ist neben der
        <gerquot>klassischen</gerquot> Zugriffsvariante auch eine
        auf dem <a href="http://java.sun.com/products/jndi/" external="yes">Java Naming and Directory Interface</a>
        (JNDI) basierende Zugriffsmethodik definiert, deren
        Verwendung --- abgesehen von der geänderten Mimik im Aufbau der DB-Verbindung
        --- identisch gestaltet ist.</p>
         <p>Jedoch ist, wie in JNDI üblich, vor dem Zugriff ein
        benanntes Objekt beim JNDI-Dienst zu registrieren.<br/>
        Im Falle von JDBC ist dies ein Objekt welches die
        Schnittstelle <a fixedType="JDK14" offset="javax/sql/DataSource.html" keyword="yes">DataSource</a> implementiert.</p>
         <p>Der Code des Beispiels <scriptRef type="example" name="JNDIS"/> zeigt die notwendigen Schritte zur
        Registrierung eines <code>MysqlDataSource</code>-Objekts, der durch den MySQL-JDBC-Treiber gelieferten
        Implementierung der Schnittstelle
        <code>DataSource</code>.</p>
         <scriptElement type="example" name="JNDIS" filename="JDBCConnect2Server.java" title="Ablage von Verbindungsinformation in einem JNDI-Verzeichnis">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCConnect2Server.java"/>
         </scriptElement>
         <p>Entsprechend der modifizierten Ablage der Verwaltungsinformation
        ändert sich die Erzeugung der
        Datenbankverbindung beim Zugriff. Hier wird nun
        zunächst über einen Zugriff auf den JNDI-Verzeichnisdienst
        das benannte <code>DataSource</code>-Objekt (es trägt den
        Namen <code>jdbc/mySrc</code> ermittelt.<br/>
        Anschließend wird durch das dem Verzeichnisdienst
        entnommene <code>DataSource</code>-Objekt die
        Datenbankverbindung (d.h. das
        <code>Connection</code>-Objekt) erzeugt.<br/>
        Alle weiteren Schritte zur Interaktion mit der Datenbank
        verlaufen dann identisch zur im Beispiel <scriptRef type="example" name="connect"/> gezeigten
        Verbindungsaufnahme.<br/>
        Der Code des Beispiels <scriptRef type="example" name="JNDIC"/>
        zeigt die notwendigen Schritte zur Ermittlung der Referenz auf
        das Objekt des Typs <code>DataSource</code> aus dem JNDI-Verzeichnis,
        sowie die Erzeugung des <code>Connection</code>-Objekts.</p>
         <scriptElement type="example" name="JNDIC" filename="JDBCConnect2.java" title="Verbindungsaufbau unter Nutzung von JNDI">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCConnect2.java"/>
         </scriptElement>
         <p>Auffallend ist die Ablage des Datenbanknamens im
        Verzeichnisdienst mittels des Methodenaufrufs
        <code>setDatabaseName</code>. Diese Verschiebung der
        Information wird durch die geänderte Mimik der
        Erzeugung des <code>Connection</code>-Objekts impliziert.
        So sieht die Implementierung dieser Methode für die Klasse
        <code>DataSource</code> keine Möglichkeit zur
        gleichzeitigen Übergabe von Anmeldenamen, Paßwort und
        Datenbank vor.<br/>
        Vielmehrnoch ist es sogar möglich diese Daten allesamt
        innerhalb des JNDI-Verzeichnisdienstes abzulegen. (Für diesen Zweck
        stehen die Methoden <code>setUser</code> bzw. <code>setPassword</code> zur Verfügung.)
        Als Konsequenz hiervon kann der Verbinungswunsch durch
        Aufruf der Methode <code>getConnection</code> ohne weitere
        Parameter erfüllt werden.<br/>
        Diese Umsetzungsweise ist vor ihrer Realisierung
        hinsichtlich des damit eintretenden Verlustes an
        Sicherheit zu prüfen, da in ihrer Folge eine
        Datenbankverbindung allein durch Kenntnis des
        JNDI-residenten Namens des
        <code>DataSource</code>-Objektes erfolgen kann.</p>
         <p>Generell wählen JDBC-Umsetzungen den Weg, jede Ausprägung eines <code>Connection</code>-Objekts
        in eine physische Datenbankverbindung abzubilden. Dieses, durchaus der intuitiven Semantik der
        <code>Connection</code>-Klasse entsprechende Vorgehen kann jedoch in realen Applikationen, begründet
        in der Vielzahl der durch das DBMS zu verwaltenden Verbindungen, zu Zugriffsengpässen führen.<br/>
        Aus diesem Grunde definiert die JDBC-Schnittstelle Operationen zur Zusammenfassung <gerquot>gleichartiger</gerquot>
        Zugriffe. Hierzu zählen Zugriffe die unter derselben Nutzerkennung auf dieselbe Datenbank abgewickelt werden.
        Diese Zugriffsform tritt insbesondere bei Anwendungen auf, die über nur einen in der Datenbank eingetragenen
        Anwender verfügen und die gesamte Nutzerverwaltung datenbanktransparent applikationsseitig abwickeln.<br/>
        Zur Optimierung von Zugriffen dieser Natur sieht die JDBC-Schnittstelle das sog. <em>Connection Pooling</em> vor,
        welches gleichartige Zugriffe bündelt.<br/>
        Das Beispiel <scriptRef type="example" name="connect3"/> zeigt eine Umsetzung:</p>
         <scriptElement type="example" name="connect3" filename="JDBCConnection3.java" title="Verbindungsaufbau unter Nutzung von Connection Pooling">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCConnection3.java"/>
         </scriptElement>
         <p>Statt für jede gewünschte Datenbankverbindung ein zusätzliches Objekt des Type <code>Connection</code>
        zu erzeugen, wird die erzeugte Verbindung zur Konstruktion eines Objektes, welches Konform zur Schnittstelle
        <a fixedType="JDK14" offset="javax/sql/PooledConnection.html" keyword="yes">PooledConnection</a> definiert ist,
        verwendet. Dieses sorgt für die Verwaltung der DB-Verbindung und stellt dieselbe physische
        Verbindung verschiedenen Anfragern zur Verfügung.<br/>
        Konsequenterweise wird daher eine neue Verbindung nicht mehr vom <code>DriverManager</code> angefordert, sondern
        durch die Methode <code>getConnection</code> der aus der Verwaltungsstruktur entnommenen <code>PooledConnection</code>
        beantragt.</p>
         <p>Aufgrund der Unterstützung des SQL-Sprachumfanges,
        durch unveränderte textuelle Propagation an das DBMS
        sind durch JDBC im Allgemeinen alle Facetten der Datenbanksprache
        nutzbar, sofern sie durch das verwendete DBMS Unterstützung finden. Hierunter fallen:</p>
         <ul>
            <li>Data Definition Language.<br/>
            Zur Erzeugung eines Datenmodells.</li>
            <li>Data Manipulation Language.<br/>
            Zur Modifikation der verwalteten Daten.</li>
            <li>Data Retrieval Language.<br/>
            Zur Anfrage der in einer Datenbank gespeicherten
            Daten.</li>
            <li>Data Control Language.<br/>
            Zur Festlegung und Kontrolle von
            Zugriffsberechtigungen.</li>
         </ul>
         <p>JDBC reflektiert jedoch nicht diese
        Sprach(-sub-)klassen selbst in der API, sondern sieht
        vielmehr ausschließlich zwei Formen des Zugriffs vor.
        Solche die tabellenwerte Resultate liefern und solche, deren Ausführung
        lediglich primitivwertige Rückgabewerte liefert.</p>
         <subsubtopic>Primitivwertige Zugriffe</subsubtopic>
         <p>Primitivwertige Datenbankzugriffe liefern, abgesehen von
        Fehler- oder Warnmeldungen, lediglich die Anzahl der
        geänderten Tupel, falls zutreffend, oder 0 zurück.<br/>
        Aus dieser Festlegung lassen sich diejenigen
        SQL-Anweisungstypen ableiten, welche als primitivwertiger
        Zugriff realisiert sind. Hierunter fallen alle Operationen
        der Datendefinition wie <code>CREATE</code> oder
        <code>ALTER TABLE</code> sowie alle Einfüge-
        (<code>INSERT</code>) Änderungs- (<code>UPDATE</code>) und
        Löschvorgänge (<code>DELETE</code>). Darüberhinaus alle
        Operationen zur Administration der Datenbank durch
        Rechtevergabe (<code>GRANT</code>, <code>REVOKE</code>).</p>
         <p>Zugriffe dieser Art werden generell durch die Methode
        <a fixedType="JDK14" offset="java/sql/Statement.html#executeUpdate(java.lang.String)" keyword="yes">executeUpdate</a>, oder einer Abart davon,
        realisiert.</p>
         <scriptElement type="example" name="createTab" title="Erstellung einer neuen Tabelle" filename="JDBCCreateTable.java" resultfile="JDBCCreateTable.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCCreateTable.java"/>
         </scriptElement>
         <p>Beispiel <scriptRef type="example" name="createTab"/>
        zeigt die notwendigen Schritte zur Erstellung der <a href="#TabEmployee">Tabelle <code>EMPLOYEE</code>
            </a> in
        der Datenbank.</p>
         <p>Nach dem (üblichen) Verbindungsaufbau (Zeile 8-24) wird
        in Zeile 27 eine Variable des Typs <a fixedType="JDK14" offset="java/sql/Statement.html" keyword="yes">Statement</a> deklariert. Auch bei
        <code>Statement</code> handelt es sich um eine durch die
        JDBC-API vordefinierte Schnittstelle, die als Bestandteil
        des JDBC-Treibers von einer Klasse implementiert
        wird.<br/>
        Ausgehend von der etablierten Datenbankverbindung wird
        durch Aufruf der Methode <a fixedType="JDK14" offset="java/sql/Connection.html#createStatement()" keyword="yes">createStatement</a>
        eine konkrete Ausprägung konform zur
        <code>Statement</code>-Schnittstelle erzeugt (Zeile
        29).</p>
         <p>Der Aufruf von <a fixedType="JDK14" offset="java/sql/Statement.html#executeUpdate(java.lang.String)" keyword="yes">executeUpdate</a> übergibt das als
        Zeichenkette abgelegte SQL-Kommando an die Datenbank zur
        Ausführung.<br/>
        Da durch <code>CREATE TABLE</code> keine Tupeländerungen vorgenommen werden ist das
        Resultat des Aufrufs der Rückgabewert <code>0</code>.</p>
         <p>Beispiel <scriptRef type="example" name="alterTab"/>
        zeigt mit dem <code>ALTER TABLE</code>-Kommando eine
        weitere Anwendung der
        <code>executeUpdate</code>-Methode.<br/>
        Auch in diesem Falle wird als Resultat <code>0</code> geliefert, da die Definition des
        Primärschlüssels keine Änderungen an den verwalteten Datensätzen vornimmt.</p>
         <scriptElement type="example" name="alterTab" title="Modifikation der Tabellendefinition" filename="JDBCAlterTable.java" resultfile="JDBCAlterTable.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCAlterTable.java"/>
         </scriptElement>
         <scriptElement type="example" name="insert1" title="Einfügen von Werten" filename="JDBCInsert1.java" resultfile="JDBCInsert1.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCInsert1.java"/>
         </scriptElement>
         <p>Beispiel <scriptRef type="example" name="insert1"/>
        zeigt den Einfügevorgang von acht Werten in die durch die
        vorangegangenen Beispiele erzeugte Tabelle
        <code>EMPLOYEE</code>.<br/>
        Jeder der Einfügevorgänge der Zeilen 36-43 führt im Rahmen einer separaten Datenbankkommunikation
        sequentiell genau einen Einfügevorgang durch, was durch den Rückgabewert <code>1</code> dokumentiert wird.</p>
         <p>Zwar ist dieses Verfahren praktikabel und erzielt die
        angestrebten Resultate, jedoch ist es unter
        Zeiteffizienzgesichtspunkten inadäquat, da sich Einfüge-
        und Kommunikationsvorgänge zahlenmäßig entsprechen.</p>
         <p>Aus diesem Grunde bietet die Schnittstelle <a fixedType="JDK14" offset="java/sql/Statement.html" keyword="yes">Statement</a> die Möglichkeit zur Bündelung
        einzelner SQL-Aufrufe in einem sog. <em>Batch</em> an.</p>
         <p>Beispiel <scriptRef type="example" name="insert2"/>
        zeigt die entsprechende Umgestaltung des vorangegangenen
        Beispiels.</p>
         <scriptElement type="example" name="insert2" title="Einfügen von Werten mittels eines Batches" filename="JDBCInsert2.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCInsert2.java"/>
         </scriptElement>
         <p>Statt der Einzelübergabe der SQL
        <code>INSERT</code>-Anweisungen werden diese nun (in Zeile
        36-43) in in einem Batch gesammelt. Hierzu werden die
        SQL-Zeichenketten durch den Aufruf <a fixedType="JDK14" offset="java/sql/Statement.html#addBatch(java.lang.String)" keyword="yes">addBatch</a> innerhalb des
        <code>Statement</code>-Objekts abgelegt und durch Aufruf
        der Methode <a fixedType="JDK14" offset="java/sql/Statement.html#executeBatch()" keyword="yes">executeBatch</a> gesammelt an das DBMS
        übergeben.<br/>
        Statt der Einzelresultate wird durch diese Aufrufvariante
        ein Array geliefert, das die Einzelrückgabewerte der als
        Batch übergebenen Aufrufe versammelt.</p>
         <p>Dies verdeutlicht nochmals das nachfolgende Beispiel.
        In ihm wird zunächst mittels <code>ALTER TABLE</code> eine
        neue Tabellenspalte zur Aufnahme des Wochentages der
        Geburt erstellt und anschließend durch SQL
        <code>UPDATE</code>-Anweisungen die benötigten Daten aus
        dem vorhandenen Geburtsdatum ermittelt.<br/>
        Auch dieses Beispiel bedient sich zur Performancebeschleunigung der Möglichkeiten des Batchaufrufes.</p>
         <scriptElement type="example" name="update1" title="Aktualisieren von Tabellendefinitionen und Werten" filename="JDBCUpdate1.java" resultfile="JDBCUpdate1.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCUpdate1.java"/>
         </scriptElement>
         <p>Die Ausführung liefert als Resultat:</p>
         <code>
            <pre>Statement No 0 changed 8 rows
Statement No 1 changed 0 rows
Statement No 2 changed 1 rows
Statement No 3 changed 0 rows
Statement No 4 changed 1 rows
Statement No 5 changed 1 rows
Statement No 6 changed 2 rows
Statement No 7 changed 3 rows
</pre>
         </code>
         <p>So werden durch den <code>ALTER TABLE</code>-Aufruf
        (Indexnummer 0) alle acht Tupel der Tabelle modifiziert,
        während die nachfolgenden Aufrufe nur Teilmengen davon
        verändern.</p>
         <p>Die nähere Betrachtung der Zeilen 37-43 des Quellcodes
        von Beispiel <scriptRef type="example" name="update1"/>
        zeigt sich, daß diese im Kern denselben Vorgang ausführen,
        nur jeweils mit variierenden Parametern.<br/>
        Zur Behandlung von Fällen dieser Problemstellung definiert
        die JDBC-API die Schnittstelle <a fixedType="JDK14" offset="java/sql/PreparedStatement.html" keyword="yes">PreparedStatement</a> als Spezialisierung
        von <code>Statement</code>.</p>
         <p>Diese Schnittstelle gestattet es, Anweisungen, die später
        an die Datenbank übermittelt werden sollen, mit
        Platzhaltern zu versehen und diese vor der Übermittlung
        mit Werten zu befüllen.<br/>
        Beispiel <scriptRef type="example" name="update2"/> zeigt die entprechende
        Modifikation des vorangegangenen Beispiels.</p>
         <scriptElement type="example" name="update2" title="Aktualisieren von Tabellendefinitionen und Werten" filename="JDBCUpdate2.java" resultfile="JDBCUpdate2.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCUpdate2.java"/>
         </scriptElement>
         <p>Im Beispiel wird neben dem Objekt des Typs <code>Statement</code>
        zusätzlich eines des Typs <code>PreparedStatement</code> erzeugt (Zeile 32).<br/>
        Die dem Konstruktor übergebene Anweisung enthält als Sonderzeichen zur Markierung der Platzhalter
        das Fragezeichen (<code>?</code>).<br/>
        Die Wochentage werde in Zeile 40, des vereinfachten Zugriffs wegen, als Array definiert.<br/>
        In den Zeilen 42 mit 46 werden die benötigten SQL-<code>UPDATE</code>-Anweisungen dynamisch
        durch Einsetzen der geeigneten Werte in den vorpräparierten Änderungsausruck erzeugt und einem eigenen
        Batch zugeordnet. Der Einsetzungsvorgang der benötigten Werte geschieht durch die Methoden
        <a fixedType="JDK14" offset="java/sql/PreparedStatement.html#setString(int, java.lang.String)" keyword="yes">setString</a>
        für zeichenkettenartige bzw. <a fixedType="JDK14" offset="java/sql/PreparedStatement.html#setInt(int, int)" keyword="yes">setInt</a> für den
        ganzzahlige Parameter. Den Methoden wird jeweils die Position des Parameters, gezählt ab 1 sowie die zu wählende Wertbelegung übermittelt.<br/>
        Zur Ausführung müssen beide Batches getrennt angefordert werden.</p>
         <subsubtopic>Tabellenwertige Zugriffe</subsubtopic>
         <p>Die in der Praxis quantitativ bedeutendste Klasse von
        Datenbankzugriffen dürfte zweifellos auf die lesende
        Ermittlung von bestehenden Daten darstellen, kurzum alle Spielarten der SQL <code>SELECT</code>-Anweisung.</p>
         <p>Für Anfragen an die Datenbank steht prinzipiell der
        gesamte durch das DBMS unterstützte SQL-Umfang zur
        Verfügung.</p>
         <p>Anfragen werden im Gegensatz zu den bisher
        betrachteten lesenden Zugriffen nicht als primivwerte
        Methoden realisiert, sondern liefern als Resultat immer
        eine Tabelle zurück.<br/>
        Diese wird durch den API-Typ <a fixedType="JDK14" offset="java/sql/ResultSet.html" keyword="yes">ResultSet</a> dargestellt.<br/>
        Zusätzlich werden Anfragen durch die Methode <a fixedType="JDK14" offset="java/sql/Statement.html#executeQuery(java.lang.String)">executeQuery</a>
        ausgeführt.</p>
         <p>Das Beispiel <scriptRef type="example" name="select1"/>
        zeigt die generische Extraktion von DB-Daten und den Zugriff auf
        Metadaten.<br/>
        Die aus der Datenbank gelesenen Ergebnistupel werden im durch <code>rs</code>
        benannten <code>ResultSet</code> abgelegt (Zeile 39). Die Resultatmenge wird
        mithilfe eines <em>Cursors</em> (Datensatzzeiger) traversiert. Hierzu wird der initial auf
        eine Ausgangsstellung vor dem ersten empfangenen Tupel positionierte Cursor durch Aufruf der Methode
        <code>next</code> solange weitergerückt, bis der letzte Datensatz verarbeitet wurde.</p>
         <p>Der Aufruf der Methode<a fixedType="JDK14" offset="java/sql/ResultSet.html#getMetaData()" keyword="yes">getMetaData</a>
        liefert deskriptive Metadaten wie Spaltenzahl sowie deren Bezeichner und Typen für die erstellte Resultattupelmenge.<br/>
        In Zeile 43 werden diese Metadaten verwendet um die
        Spaltennamen der extrahierten Attribute anzuzeigen.<br/>
        Zeile 47-52 liest die einzelnen Werte jedes Tupels mittels
        <a fixedType="JDK14" offset="java/sql/ResultSet.html#getObject(int)" keyword="yes">getObject</a> aus und stellt sie am
        Bildschirm dar.</p>
         <scriptElement type="example" name="select1" title="Auslesen von Daten und Metadaten" filename="JDBCSelect1.java" resultfile="JDBCSelect1.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect1.java"/>
         </scriptElement>
         <p>Neben im Beispiel <scriptRef type="example" name="select1"/>
        gezeigten Verarbeitung in exakter der Ablagereihenfolge der Datenbank
        kann auch durch Definition eines Cursors die Traversierung in
        inverser Ablagerichtung erreicht werden.<br/>
        Das nachfolgende Beispiel illustriert das entsprechende Vorgehen durch anfängliche Positionierung
        des Cursors ans Ende der empfangenen Daten (d.h. nach dem letzten Datensatz) und
        anschließendes schrittweises Rückpositionieren durch Aufruf der Methode <code>previous</code>.</p>
         <scriptElement type="example" name="select5" title="Auslesen von Daten in invertierter Reihenfolge" filename="JDBCSelect5.java" resultfile="JDBCSelect5.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect5.java"/>
         </scriptElement>
         <p>Ferner kann der Cursor wahlfrei auf eine beliebige Position der Ergebnisrelation gesetzt werden.<br/>
        Das nachfolgende Beispiel zeigt dies. Ferner illustriert es das Vorgehen zur Größenermittlung
        des resultierenden <code>ResultSet</code>s durch das Aufrufpaar <code>last</code> und <code>getRow</code>, welches
        zunächst den Cursor auf den letzten aus der Datenbank extrahierten Datensatz positioniert und anschließend dessen
        Nummer liefert.</p>
         <scriptElement type="example" name="select6" title="Auslesen von Daten in wahlfreier Reihenfolge" filename="JDBCSelect6.java" resultfile="JDBCSelect6.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect6.java"/>
         </scriptElement>
         <p>Wird der benötigte <code>ResultSet</code> geeignet
        (d.h. mit den Parameter <code>CONCUR_UPDATABLE</code>)
        (siehe Zeile 49) initialisiert, so können Änderungen, die im
        Hauptspeicher durch die JDBC-API durchgeführt werden, in
        die Datenbank persistiert werden.<br/>
        Beispiel <scriptRef type="example" name="select2"/> zeigt dies exemplarisch für den
        Einfügevorgang eines neuen Tupels.</p>
         <p>Die Voraussetzungen für Einfüge- und
        Aktualisierungsvorgänge entstprechen denen von
        <em>updatable views</em>, d.h. die Daten dürfen nur aus
        genau einer Tabelle entnommen sein und müssen den
        Primärschlüssel enthalten.</p>
         <scriptElement type="example" name="select2" title="Auslesen und Einfügen von Daten" filename="JDBCSelect2.java" resultfile="JDBCSelect2.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect2.java"/>
         </scriptElement>
         <p>Auf dieselbe Weise können auch Tupel einer Relation
        verändert werden. Hierzu stehen eine Reihe von
        <code>updateXXX</code>-Methoden zur Verfügung, wobei
        <code>XXX</code> für den Typ des zu aktualisierenden
        Attributs steht.<br/>
        Nach durchgeführter Modifikation der
        hauptspeicherresidenten Werte werden diese durch <a fixedType="JDK14" offset="java/sql/ResultSet.html#updateRow()" keyword="yes">updateRow</a> in die Datenbank
        rückgeschrieben.<br/>
        Beispiel <scriptRef type="example" name="select3"/> zeigt dies:</p>
         <scriptElement type="example" name="select3" title="Modifizieren von Daten" filename="JDBCSelect3.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect3.java"/>
         </scriptElement>
         <p>Analog vollzieht sich der Löschvorgang mittels <a fixedType="JDK14" offset="java/sql/ResultSet.html#deleteRow()" keyword="yes">deleteRow</a>:</p>
         <scriptElement type="example" name="select4" title="Löschen von Daten" filename="JDBCSelect4.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect4.java"/>
         </scriptElement>
         <p>Die bisher betrachteten Varianten extrahieren Daten aus der Datenbank im Stile einer Momentaufnahme
        (<em>snapshot</em>) zum Zeitpunkt der Anfrage. Die einmal angefragten Inhalte können sich jedoch noch zur
        Laufzeit der zugreifenden JDBC-Applikation datenbankseitig ändern, wenn sie durch eine andere Applikation
        neu geschrieben werden. Zur Gewährleistung der Konsistenz des extrahierten Snapshots mit den tatsächlichen
        Datenbankinhalten steht die Operation <a offset="java/sql/ResultSet.html#rowUpdated()" fixedType="JDK14" keyword="yes">rowUpdated</a>
        zur Verfügung. Sie ermittelt ob der im Hauptspeicher befindliche Wert mit dem aktuellen Datenbankinhalt
        übereinstimmt, d.h. ob der DB-Inhalt aktualisiert wurde.<br/>
        Beispiel <scriptRef type="example" name="select7"/> zeigt ein Umsetzungsbeispiel.</p>
         <scriptElement type="example" name="select7" title="Test auf geänderte Daten" filename="JDBCSelect7.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect7.java"/>
         </scriptElement>
         <subsubtopic name="JDBCPerformance">Performancebetrachtungen</subsubtopic>
         <illustration id="JDBCPerf" width="621" caption="JDBC-Geschwindigkeitsvergleich" gfx="ebe/JDBCPerf.gif"/>
         <p>Die Abbildung zeigt die Ergebnisse einiger
        Geschwindigkeitsmessungen als Vergleich zwischen dem
        Zugriff auf eine MySQL-Datenbank unter Nutzung der
        Textschnittstelle und der Abwicklung derselben Zugriffe
        mittels JDBC.</p>
         <p>Zur Messung wurde eine nicht-indexierte Datenbank mit 10<sup>7</sup>
        Einträgen verwendet die aus der Relation <code>tab</code> bestand. Deren Tupel wurden
        aus Paaren von 36-Byte großen UUIDs gemäß dem <a href="http://www1.ics.uci.edu/~ejw/authoring/uuid-guid/draft-leach-uuids-guids-01.txt">Spezifikationsentwurf
        der IETF</a> gebildet.</p>
         <p>Zur Zeitmessung wurden folgende Einzeloperationen
        betrachtet:</p>
         <ul>
            <li>
               <b>Insert</b>: <code>INSERT INTO tab
            VALUES(...)</code>
               <br/>
            Die Werte wurden unter Deaktivierung des Autocommit
            sequentiell eingefügt.</li>
            <li>
               <b>Select (ohne Ausgabe)</b>: <code>SELECT COUNT(*) FROM
            tab</code>
               <br/>
            Die ermittelte Gesamtzahl wurde nicht am Bildschirm
            ausgegeben.</li>
            <li>
               <b>Select (mit Ausgabe)</b>: <code>SELECT * FROM
            tab</code>
               <br/>
            Die Resultate wurden durch den Standarclient bzw. eine selbsterstellte (textmode)
            Java-Implementierung ausgegeben.</li>
            <li>
               <b>Update</b>: <code>UPDATE tab SET UUID1="X" WHERE
            UUID1&lt;&gt;"X"</code>
               <br/>
            Durch die Initialisierung der Werte mit UUID-Einträgen
            wird sichergestellt, daß alle Tupel aktualisiert
            werden, da sie in keinem Fall den Wert <code>X</code>
            enthalten.</li>
            <li>
               <b>Delete</b>: <code>DELETE FROM tab WHERE
            UUID2&lt;&gt;"X"</code>
               <br/>
             Durch die Initialisierung der Werte mit UUID-Einträgen
            wird sichergestellt, daß alle Tupel aktualisiert
            werden, da sie in keinem Fall den Wert <code>X</code>
            enthalten.</li>
         </ul>
         <p>Insgesamt zeigt sich ein ausgewogenes Bild, in welchem
        der JDBC-Zugriff lediglich bei datenintensiven Zugriffen
        (große Mengen schreibender Zugriffe bei <code>INSERT</code>
        bzw. große Mengen lesender Operationen bei
        <code>SELECT</code>) im Bereich von fünf Prozent
        zurückliegt.</p>
         <p>Diese enge Vergleichbarkeit der beiden Zugriffsmodi
        rührt von den Realisierung des eingesetzten JDBC-Treibers
        her; insbesondere von der Handhabung der physischen
        Datenbankverbindung auf Ebene des Netzwerkprotokolls.</p>
         <subsubtopic name="SQLDT">SQL3-Datentypen</subsubtopic>
         <p>Die JDBC-API unterstützt mit Zugriffsmethoden auf die Datentypen <code>BLOB</code>, <code>CLOB</code>,
        <code>ARRAY</code>, <code>Object</code> und <code>Ref</code> bereits eine Untermenge des <a href="http://www.iso.ch/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=26196&amp;ICS1=35&amp;ICS2=60&amp;ICS3=">SQL:1999-Standards</a>.
        So können, vorausgesetzt das durch JDBC angesprochene DBMS unterstützt dies, große unstrukturierte Binär- oder Textdaten
        sowie einfache verschachtelte Tabellen, mithin <a href="../datenbanken/script.html#NF2Ref">NF<sup>2</sup>-Strukturen</a> verwaltet werden.</p>
         <p>Beispiel <scriptRef type="example" name="select8"/> zeigt den Zugriff
        auf ein als eingebettete Tabelle realisiertes mengenwertiges Attribut.<br/>
        Die Beispieldatenbank wurde hierfür wie folgt modifiziert:</p>
         <code>
            <pre>alter table EMPLOYEE ADD CAR SET('53M91','521R4', 'LLO415', 'XNU457');
update EMPLOYEE set CAR='XNU457' where SSN=123456789;
update EMPLOYEE set CAR='XNU457,521R4'  where SSN="999887777";</pre>
         </code>
         <scriptElement type="example" name="select8" title="Zugriff auf ein mengenwertiges Attribut" filename="JDBCSelect8.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect8.java"/>
         </scriptElement>
         <p>Das Beispiel unterstreicht die Rolle der mengenwertigen Attribute als eingebettete Tabellen.
        So erfolgt der Zugriff auf die Einzelwerte des Attributs <code>CAR</code> identisch zur Ermittlung der
        Resultatmenge der SQL-Anfrage mittels <code>getResultSet</code>. Auch die Traversierung der einzelnen
        <code>CAR</code>-Elemente erfolgt äquivalent.</p>
         <p>Die Aufnahme der <em>large objects</em> in ihrer Ausprägungsform als <em>Character Large Objects</em> (CLOB)
        oder <em>Binary Large Objects</em> (BLOB) stellen eine der zentralen Erweiterungen des SQL:1999-Standards
        gegenüber seinen Vorgängern dar.<br/>
        Zwar ist die Ablage großer unstrukturierter Datenobjekte in relationalen Datenbanken konzeptionell durchaus diskussionswert,
        jedoch in der Praxis oftmals, trotz der teilweise erheblichen Geschwindigkeitseinbußen im Zugriff (so benötigt die Ausführung
        der Beispielapplikation mit einem 10<sup>6</sup> Byte großen Datenstrom 1,1 Sekunden, während dieselbe
        Operation dateisystembasiert in 0,1 Sekunde abläuft), gewünscht.<br/>
        Beispiel <scriptRef type="example" name="select9"/> zeigt die notwendigen Schritte zur Ablage und erneuten Auslese
        eines aus einer Datei gewonnen Binärdatenstroms in der Datenbank.<br/>
        Die Beispieldatenbank wurde hierfür um ein Attribut zur Aufnahme binärer Daten erweitert:<br/>
            <code>ALTER TABLE EMPLOYEE ADD binData blob;</code>
         </p>
         <scriptElement type="example" name="select9" title="Verarbeitung unstrukturierter Binärdaten" filename="JDBCSelect9.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCSelect9.java"/>
         </scriptElement>
         <p>Die Binärdaten können naturgemäß nicht direkt in die SQL-<code>UPDATE</code>-Anweisung eingebunden werden,
         sie werden daher einer mittels <code>prepareStatement</code> vorerzeugten Anweisung durch Aufruf der Methode <a fixedType="JDK14" offset="java/sql/PreparedStatement.html#setBinaryStream(int, java.io.InputStream, int)" keyword="yes">setBinaryStream</a>
         übergeben.</p>
         <subsubtopic name="trans">Transaktionssteuerung</subsubtopic>
         <p>Zur Steuerung des transaktionalen Verhaltens einer JDBC-Anfrage bietet die Klasse <code>Connection</code>
         verschiedene Methoden an:</p>
         <ul>
            <li>Abfrage der aktuellen Isolationsstufe: <a fixedType="JDK14" offset="file:///C:/j2sdk/docs/api/java/sql/Connection.html#getTransactionIsolation()" keyword="yes">getIsolationLevel</a>.<br/>
            Hierbei werden fünf Stufen unterschieden:
                <ul>
                  <li>
                     <a fixedType="JDK14" offset="java/sql/Connection.html#TRANSACTION_NONE" keyword="yes">TRANSACTION_NONE</a>: Keinerlei Transaktionsunterstützung</li>
                  <li>
                     <a fixedType="JDK14" offset="java/sql/Connection.html#TRANSACTION_READ_UNCOMMITTED" keyword="yes">TRANSACTION_READ_UNCOMMITTED</a>: Auch nicht durch <code>commit</code> freigegebene
                    Daten werden gelesen. Es können daher <em>dirty reads</em>, Nicht-wiederholbare- und Phantomlesevorgänge
                    auftreten.</li>
                  <li>
                     <a fixedType="JDK14" offset="java/sql/Connection.html#TRANSACTION_READ_COMMITTED" keyword="yes">TRANSACTION_READ_COMMITTED</a>: Nur durch <code>commit</code> freigegebene
                    Daten werden gelesen. nichtwiederholbare- und Phantomlesevorgänge können jedoch auftreten.</li>
                  <li>
                     <a fixedType="JDK14" offset="java/sql/Connection.html#TRANSACTION_REPEATABLE_READ" keyword="yes">TRANSACTION_REPEATABLE_READ</a>: Innerhalb einer Transaktion können die verarbeiteten
                    Daten nicht durch eine andere Transaktion verändert werden. Das Auftreten von <em>dirty reads</em> und
                    nichtwiederholbaren Lesevorgängen ist daher ausgeschlossen, Phantomlesevorgänge sind jedoch weiterhin möglich.</li>
                  <li>
                     <a fixedType="JDK14" offset="java/sql/Connection.html#TRANSACTION_SERIALIZABLE" keyword="yes">TRANSACTION_SERIALIZABLE</a>: Strikte Isolation aller Transaktionen, auf dieser
                    Stufe sind auch Phantomlesevorgänge ausgeschlossen.</li>
               </ul>
                Jede Stufe geht zwar mit einer gesteigerten Qualität der durch eine Transaktion verarbeiteten Daten
                einher, jedoch senkt gleichzeitig eine strikterere Isolationsstufe die Anzahl der gleichzeitigen
                Zugriffe auf die Datenbank und damit die Gesamtsystemperformance.
            </li>
            <li>Setzen der Isolationsstufe: <a fixedType="JDK14" offset="java/sql/Connection.html#setTransactionIsolation(int)" keyword="yes">setTransactionIsolation</a>
            </li>
            <li>(De-)Aktivierung der automatischen Freigabe: <a fixedType="JDK14" offset="java/sql/Connection.html#setAutoCommit(boolean)" keyword="yes">setAutoCommit</a>. Die Übergabe von <code>true</code> bewirkt die Aktivierung des Modus bei
            dem jede Einzelanweisung sofort persistent übernommen und für andere Transaktionen sichtbar wird.<br/>
            Standardmäßig ist diese Option aktiviert. Ihr aktueller Zustand kann per <a fixedType="JDK14" offset="java/sql/Connection.html#getAutoCommit()" keyword="yes">getAutoCommit</a> ermittelt werden.</li>
            <li>Freigabe von Änderungen: <a fixedType="JDK14" offset="java/sql/Connection.html#commit()" keyword="yes">commit</a>.</li>
            <li>Rücknahme von Änderungen: <a fixedType="JDK14" offset="java/sql/Connection.html#rollback()" keyword="yes">rollback</a>.</li>
            <li>Rücknahme von Änderungen bis zu definiertem Sicherungspunkt: <a fixedType="JDK14" offset="java/sql/Connection.html#rollback(java.sql.Savepoint)" keyword="yes">rollback(Savepoint s)</a>.</li>
            <li>Setzen eines Sicherungspunktes: <a fixedType="JDK14" offset="java/sql/Connection.html#setSavepoint()" keyword="yes">setSavepoint</a>.</li>
         </ul>
         <p>Beispiel <scriptRef type="example" name="transact1"/> zeigt
        die Nutzung des Transaktionskonzepts.<br/>
        Zunächst wird die aktuelle Isolationsstufe ermittelt und geprüft ob
        das angesprochene DBMS die höchste durch JDBC vorhergesehene Isolationsstufe unterstützt.<br/>
        Nach Abschaltung der automatischen Änderungsübernahme (<code>setAutoCommit(false)</code>) werden
        zunächst zwei Tupel in die Tabelle <code>EMPLOYEE</code> eingefügt, die jedoch nur innerhalb der
        laufenden Transaktion sichtbar werden, für alle anderen Transaktionen innerhalb des DBMS bleiben die
        neuen Werte (zunächst) unsichtbar.<br/>
        Eine angenommene Fehlersituation führt zum Rücksetzen der Transaktion durch (<code>rollback</code>).<br/>
        Nach Abschluß des Programms wurden zwar die beiden ersten Werte lokal in die Datenbank übernommen, aber noch
        innerhalb der laufenden Transaktion wieder daraus entfernt, weshalb sie zu keinem Zeitpunkt für andere
        Datenbankbenutzer sichtbar waren.</p>
         <scriptElement type="example" name="trans1" title="Transaktionsverarbeitung" filename="JDBCTransact1.java" resultfile="JDBCTransact1.out">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCTransact1.java"/>
         </scriptElement>
         <p>Neben dem Zurücksetzen einer vollständigen Transaktion bietet
        die JDBC-API auch die Möglichkeit alle Schritte bis zu einem anwenderdefierten aus
        der Datenbank zu entfernen.<br/>
        Beispiel <scriptRef type="example" name="trans2"/> zeigt dies unter Verwendung der
        Methode <code>setSavepoint</code> zur Definition eines Sicherungspunktes und
        <code>rollback(sp)</code> zum Zurücksetzen bis zu diesem Sicherungspunkt.</p>
         <scriptElement type="example" name="trans2" title="Transaktionsverarbeitung mit Sicherungspunkten" filename="JDBCTransact2.java">
            <importText URI="../development/vorlesung/sharedScriptParts/jdbcExamples/JDBCTransact2.java"/>
         </scriptElement>
         <subsubtopic name="JDBCNET">Netzwerkverkehr</subsubtopic>
         <p>Der Netzwerkmitschnitt zeigt den TCP-Kommunikationsverlauf
        der SQL-Anfrage <code>SELECT * FROM EMPLOYEE;</code>.<br/>
        Die vom Anfrager an den MySQL-Server übermittelten Datenanteile sind rot hervorgehoben. Zusätzlich
        sind die für eine gleichwertige native Kommunikation anfallenden Daten berücksichtigt. Ihre Anteile
        entsprechen den zusätzlich durch Fettdruck hervorgehobenen.</p>
         <code>
            <pre>
               <span xml:base="file:/I:/development/vorlesung/sharedScriptParts/jdbc/readJDBC.hex">0000 <b>4  00 00 00 \n 4  .  0  .  1  2  -  s  t  a  n  d  a  r  d  -  l  o  g  00 '  00 00 00 N  4  V</b>
0020 <b>5  G  D  a  9  00 ,     \b 02 00 00 00 00 00 00 00 00 00 00 00 <font color="red">00 00 00 14 00 00 01 87 00 ÿ  ÿ</font>
                  </b>
0040 <b>
                     <font color="red">ÿ  m  a  r  i  o  00 N  W  N  J  S  ]  L  K  00</font> 03 00 00 02 00 00 00 \t <font color="red">00 00 00 02 j  d  b  c</font>
                  </b>
0060 <b>
                     <font color="red">t  e  s  t</font>  03 00 00 01 00 00 00 </b>
                  <font color="red">0f 00 00 00 03 S  H  O  W     V  A  R  I  A  B  L  E  S</font>  01 00
0080 00 01 02 19 00 00 02 00 \r V  a  r  i  a  b  l  e  _  n  a  m  e  03 1e 00 00 01 þ  03 01 00 1f
00a0 11 00 00 03 00 05 V  a  l  u  e  03 00 01 00 01 þ  03 01 00 1f 01 00 00 04 þ  \f 00 00 05 \b b
00c0 a  c  k  _  l  o  g  02 5  0  7  00 00 06 07 b  a  s  e  d  i  r  .  /  o  p  t  /  r  a  i  d
00e0 /  m  y  s  q  l  -  s  t  a  n  d  a  r  d  -  4  .  0  .  1  2  -  p  c  -  l  i  n  u  x  -
0100 i  6  8  6  /  18 00 00 07 11 b  i  n  l  o  g  _  c  a  c  h  e  _  s  i  z  e  05 3  2  7  6
0120 8     00 00 \b 17 b  u  l  k  _  i  n  s  e  r  t  _  b  u  f  f  e  r  _  s  i  z  e  07 8  3
0140 8  8  6  0  8  15 00 00 \t \r c  h  a  r  a  c  t  e  r  _  s  e  t  06 l  a  t  i  n  1  á  00
0160 00 \n 0e c  h  a  r  a  c  t  e  r  _  s  e  t  s  Ñ  l  a  t  i  n  1     b  i  g  5     c  z
0180 e  c  h     e  u  c  _  k  r     g  b  2  3  1  2     g  b  k     l  a  t  i  n  1  _  d  e
01a0 s  j  i  s     t  i  s  6  2  0     u  j  i  s     d  e  c  8     d  o  s     g  e  r  m  a  n
01c0 1     h  p  8     k  o  i  8  _  r  u     l  a  t  i  n  2     s  w  e  7     u  s  a  7     c
01e0 p  1  2  5  1     d  a  n  i  s  h     h  e  b  r  e  w     w  i  n  1  2  5  1     e  s  t  o
0200 n  i  a     h  u  n  g  a  r  i  a  n     k  o  i  8  _  u  k  r     w  i  n  1  2  5  1  u  k
0220 r     g  r  e  e  k     w  i  n  1  2  5  0     c  r  o  a  t     c  p  1  2  5  7     l  a  t
0240 i  n  5  15 00 00 0b 11 c  o  n  c  u  r  r  e  n  t  _  i  n  s  e  r  t  02 O  N  12 00 00 \f
0260 0f c  o  n  n  e  c  t  _  t  i  m  e  o  u  t  01 5  17 00 00 \r 15 c  o  n  v  e  r  t  _  c
0280 h  a  r  a  c  t  e  r  _  s  e  t  00 &lt;  00 00 0e 07 d  a  t  a  d  i  r  3  /  o  p  t  /  r
02a0 a  i  d  /  m  y  s  q  l  -  s  t  a  n  d  a  r  d  -  4  .  0  .  1  2  -  p  c  -  l  i  n
02c0 u  x  -  i  6  8  6  /  d  a  t  a  /  13 00 00 0f 0f d  e  l  a  y  _  k  e  y  _  w  r  i  t
02e0 e  02 O  N  19 00 00 10 14 d  e  l  a  y  e  d  _  i  n  s  e  r  t  _  l  i  m  i  t  03 1  0
0300 0  1b 00 00 11 16 d  e  l  a  y  e  d  _  i  n  s  e  r  t  _  t  i  m  e  o  u  t  03 3  0  0
0320 18 00 00 12 12 d  e  l  a  y  e  d  _  q  u  e  u  e  _  s  i  z  e  04 1  0  0  0  \n 00 00 13
0340 05 f  l  u  s  h  03 O  F  F  \r 00 00 14 \n f  l  u  s  h  _  t  i  m  e  01 0  !  00 00 15 11
0360 f  t  _  b  o  o  l  e  a  n  _  s  y  n  t  a  x  0e +     -  &gt;  &lt;  (  )  ~  *  :  "  "  &amp;  |
0380 12 00 00 16 0f f  t  _  m  i  n  _  w  o  r  d  _  l  e  n  01 4  14 00 00 17 0f f  t  _  m  a
03a0 x  _  w  o  r  d  _  l  e  n  03 2  5  4  1c 00 00 18 18 f  t  _  m  a  x  _  w  o  r  d  _  l
03c0 e  n  _  f  o  r  _  s  o  r  t  02 2  0  1c 00 00 19 10 f  t  _  s  t  o  p  w  o  r  d  _  f
03e0 i  l  e  \n (  b  u  i  l  t  -  i  n  )  \f 00 00 1a \b h  a  v  e  _  b  d  b  02 N  O  0f 00
0400 00 1b \n h  a  v  e  _  c  r  y  p  t  03 Y  E  S  10 00 00 1c 0b h  a  v  e  _  i  n  n  o  d
0420 b  03 Y  E  S  0e 00 00 1d \t h  a  v  e  _  i  s  a  m  03 Y  E  S  \r 00 00 1e \t h  a  v  e
0440 _  r  a  i  d  02 N  O  16 00 00 1f \f h  a  v  e  _  s  y  m  l  i  n  k  \b D  I  S  A  B  L
0460 E  D  10 00 00    \f h  a  v  e  _  o  p  e  n  s  s  l  02 N  O  15 00 00 !  10 h  a  v  e  _
0480 q  u  e  r  y  _  c  a  c  h  e  03 Y  E  S  0b 00 00 "  \t i  n  i  t  _  f  i  l  e  00 (  00
04a0 00 #  1f i  n  n  o  d  b  _  a  d  d  i  t  i  o  n  a  l  _  m  e  m  _  p  o  o  l  _  s  i
04c0 z  e  07 2  0  9  7  1  5  2  !  00 00 $  17 i  n  n  o  d  b  _  b  u  f  f  e  r  _  p  o  o
04e0 l  _  s  i  z  e  \b 1  6  7  7  7  2  1  6  -  00 00 %  15 i  n  n  o  d  b  _  d  a  t  a  _
0500 f  i  l  e  _  p  a  t  h  16 i  b  d  a  t  a  1  :  1  0  M  :  a  u  t  o  e  x  t  e  n  d
0520 16 00 00 &amp;  14 i  n  n  o  d  b  _  d  a  t  a  _  h  o  m  e  _  d  i  r  00 19 00 00 '  16 i
0540 n  n  o  d  b  _  f  i  l  e  _  i  o  _  t  h  r  e  a  d  s  01 4  18 00 00 (  15 i  n  n  o
0560 d  b  _  f  o  r  c  e  _  r  e  c  o  v  e  r  y  01 0  1c 00 00 )  19 i  n  n  o  d  b  _  t
0580 h  r  e  a  d  _  c  o  n  c  u  r  r  e  n  c  y  01 8  !  00 00 *  1e i  n  n  o  d  b  _  f
05a0 l  u  s  h  _  l  o  g  _  a  t  _  t  r  x  _  c  o  m  m  i  t  01 1  18 00 00 +  14 i  n  n
05c0 o  d  b  _  f  a  s  t  _  s  h  u  t  d  o  w  n  02 O  N  15 00 00 ,  13 i  n  n  o  d  b  _
05e0 f  l  u  s  h  _  m  e  t  h  o  d  00 1c 00 00 -  18 i  n  n  o  d  b  _  l  o  c  k  _  w  a
0600 i  t  _  t  i  m  e  o  u  t  02 5  0  17 00 00 .  13 i  n  n  o  d  b  _  l  o  g  _  a  r  c
0620 h  _  d  i  r  02 .  /  17 00 00 /  12 i  n  n  o  d  b  _  l  o  g  _  a  r  c  h  i  v  e  03
0640 O  F  F  1f 00 00 0  16 i  n  n  o  d  b  _  l  o  g  _  b  u  f  f  e  r  _  s  i  z  e  07 8
0660 3  8  8  6  0  8  1d 00 00 1  14 i  n  n  o  d  b  _  l  o  g  _  f  i  l  e  _  s  i  z  e  07
0680 5  2  4  2  8  8  0  1c 00 00 2  19 i  n  n  o  d  b  _  l  o  g  _  f  i  l  e  s  _  i  n  _
06a0 g  r  o  u  p  01 2  1d 00 00 3  19 i  n  n  o  d  b  _  l  o  g  _  g  r  o  u  p  _  h  o  m
06c0 e  _  d  i  r  02 .  /  1d 00 00 4  1a i  n  n  o  d  b  _  m  i  r  r  o  r  e  d  _  l  o  g
06e0 _  g  r  o  u  p  s  01 1  1a 00 00 5  13 i  n  t  e  r  a  c  t  i  v  e  _  t  i  m  e  o  u
0700 t  05 2  8  8  0  0  18 00 00 6  10 j  o  i  n  _  b  u  f  f  e  r  _  s  i  z  e  06 1  3  1
0720 0  7  2  19 00 00 7  0f k  e  y  _  b  u  f  f  e  r  _  s  i  z  e  \b 1  6  7  7  7  2  1  6
0740 L  00 00 8  \b l  a  n  g  u  a  g  e  B  /  o  p  t  /  r  a  i  d  /  m  y  s  q  l  -  s  t
0760 a  n  d  a  r  d  -  4  .  0  .  1  2  -  p  c  -  l  i  n  u  x  -  i  6  8  6  /  s  h  a  r
0780 e  /  m  y  s  q  l  /  e  n  g  l  i  s  h  /  17 00 00 9  13 l  a  r  g  e  _  f  i  l  e  s
07a0 _  s  u  p  p  o  r  t  02 O  N  10 00 00 :  \f l  o  c  a  l  _  i  n  f  i  l  e  02 O  N  15
07c0 00 00 ;  10 l  o  c  k  e  d  _  i  n  _  m  e  m  o  r  y  03 O  F  F  \b 00 00 &lt;  03 l  o  g
07e0 03 O  F  F  0f 00 00 =  \n l  o  g  _  u  p  d  a  t  e  03 O  F  F  0b 00 00 &gt;  07 l  o  g  _
0800 b  i  n  02 O  N  16 00 00 ?  11 l  o  g  _  s  l  a  v  e  _  u  p  d  a  t  e  s  03 O  F  F
0820 15 00 00 @  10 l  o  g  _  s  l  o  w  _  q  u  e  r  i  e  s  03 O  F  F  11 00 00 A  \f l  o
0840 g  _  w  a  r  n  i  n  g  s  03 O  F  F  13 00 00 B  0f l  o  n  g  _  q  u  e  r  y  _  t  i
0860 m  e  02 1  0  19 00 00 C  14 l  o  w  _  p  r  i  o  r  i  t  y  _  u  p  d  a  t  e  s  03 O
0880 F  F  1b 00 00 D  16 l  o  w  e  r  _  c  a  s  e  _  t  a  b  l  e  _  n  a  m  e  s  03 O  F
08a0 F  1b 00 00 E  12 m  a  x  _  a  l  l  o  w  e  d  _  p  a  c  k  e  t  07 1  0  4  7  5  5  2
08c0 !  00 00 F  15 m  a  x  _  b  i  n  l  o  g  _  c  a  c  h  e  _  s  i  z  e  \n 4  2  9  4  9
08e0 6  7  2  9  5  1b 00 00 G  0f m  a  x  _  b  i  n  l  o  g  _  s  i  z  e  \n 1  0  7  3  7  4
0900 1  8  2  4  14 00 00 H  0f m  a  x  _  c  o  n  n  e  c  t  i  o  n  s  03 1  0  0  16 00 00 I
0920 12 m  a  x  _  c  o  n  n  e  c  t  _  e  r  r  o  r  s  02 1  0  17 00 00 J  13 m  a  x  _  d
0940 e  l  a  y  e  d  _  t  h  r  e  a  d  s  02 2  0  1d 00 00 K  13 m  a  x  _  h  e  a  p  _  t
0960 a  b  l  e  _  s  i  z  e  \b 1  6  7  7  7  2  1  6  19 00 00 L  \r m  a  x  _  j  o  i  n  _
0980 s  i  z  e  \n 4  2  9  4  9  6  7  2  9  5  15 00 00 M  0f m  a  x  _  s  o  r  t  _  l  e  n
09a0 g  t  h  04 1  0  2  4  17 00 00 N  14 m  a  x  _  u  s  e  r  _  c  o  n  n  e  c  t  i  o  n
09c0 s  01 0  12 00 00 O  0e m  a  x  _  t  m  p  _  t  a  b  l  e  s  02 3  2     00 00 P  14 m  a
09e0 x  _  w  r  i  t  e  _  l  o  c  k  _  c  o  u  n  t  \n 4  2  9  4  9  6  7  2  9  5  *  00 00
0a00 Q  1f m  y  i  s  a  m  _  m  a  x  _  e  x  t  r  a  _  s  o  r  t  _  f  i  l  e  _  s  i  z
0a20 e  \t 2  6  8  4  3  5  4  5  6  %  00 00 R  19 m  y  i  s  a  m  _  m  a  x  _  s  o  r  t  _
0a40 f  i  l  e  _  s  i  z  e  \n 2  1  4  7  4  8  3  6  4  7  1b 00 00 S  16 m  y  i  s  a  m  _
0a60 r  e  c  o  v  e  r  _  o  p  t  i  o  n  s  03 O  F  F     00 00 T  17 m  y  i  s  a  m  _  s
0a80 o  r  t  _  b  u  f  f  e  r  _  s  i  z  e  07 8  3  8  8  6  0  8  17 00 00 U  11 n  e  t  _
0aa0 b  u  f  f  e  r  _  l  e  n  g  t  h  04 8  1  9  2  14 00 00 V  10 n  e  t  _  r  e  a  d  _
0ac0 t  i  m  e  o  u  t  02 3  0  13 00 00 W  0f n  e  t  _  r  e  t  r  y  _  c  o  u  n  t  02 1
0ae0 0  15 00 00 X  11 n  e  t  _  w  r  i  t  e  _  t  i  m  e  o  u  t  02 6  0  \b 00 00 Y  03 n
0b00 e  w  03 O  F  F  13 00 00 Z  10 o  p  e  n  _  f  i  l  e  s  _  l  i  m  i  t  01 0  F  00 00
0b20 [  \b p  i  d  _  f  i  l  e  &lt;  /  o  p  t  /  r  a  i  d  /  m  y  s  q  l  -  s  t  a  n  d
0b40 a  r  d  -  4  .  0  .  1  2  -  p  c  -  l  i  n  u  x  -  i  6  8  6  /  d  a  t  a  /  l  i
0b60 n  u  x  .  p  i  d  0b 00 00 \  \t l  o  g  _  e  r  r  o  r  00 \n 00 00 ]  04 p  o  r  t  04
0b80 3  3  0  6  14 00 00 ^  10 p  r  o  t  o  c  o  l  _  v  e  r  s  i  o  n  02 1  0  18 00 00 _
0ba0 10 r  e  a  d  _  b  u  f  f  e  r  _  s  i  z  e  06 1  3  1  0  7  2  1c 00 00 `  14 r  e  a
0bc0 d  _  r  n  d  _  b  u  f  f  e  r  _  s  i  z  e  06 2  6  2  1  4  4  14 00 00 a  11 r  p  l
0be0 _  r  e  c  o  v  e  r  y  _  r  a  n  k  01 0  1a 00 00 b  11 q  u  e  r  y  _  c  a  c  h  e
0c00 _  l  i  m  i  t  07 1  0  4  8  5  7  6  13 00 00 c  10 q  u  e  r  y  _  c  a  c  h  e  _  s
0c20 i  z  e  01 0  14 00 00 d  10 q  u  e  r  y  _  c  a  c  h  e  _  t  y  p  e  02 O  N  \f 00 00
0c40 e  \t s  e  r  v  e  r  _  i  d  01 1  17 00 00 f  11 s  l  a  v  e  _  n  e  t  _  t  i  m  e
0c60 o  u  t  04 3  6  0  0  19 00 00 g  15 s  k  i  p  _  e  x  t  e  r  n  a  l  _  l  o  c  k  i
0c80 n  g  02 O  N  14 00 00 h  0f s  k  i  p  _  n  e  t  w  o  r  k  i  n  g  03 O  F  F  17 00 00
0ca0 i  12 s  k  i  p  _  s  h  o  w  _  d  a  t  a  b  a  s  e  03 O  F  F  13 00 00 j  10 s  l  o
0cc0 w  _  l  a  u  n  c  h  _  t  i  m  e  01 2  17 00 00 k  06 s  o  c  k  e  t  0f /  t  m  p  /
0ce0 m  y  s  q  l  .  s  o  c  k  18 00 00 l  10 s  o  r  t  _  b  u  f  f  e  r  _  s  i  z  e  06
0d00 5  2  4  2  8  0  0b 00 00 m  \b s  q  l  _  m  o  d  e  01 0  0f 00 00 n  0b t  a  b  l  e  _
0d20 c  a  c  h  e  02 6  4  12 00 00 o  \n t  a  b  l  e  _  t  y  p  e  06 I  N  N  O  D  B  14 00
0d40 00 p  11 t  h  r  e  a  d  _  c  a  c  h  e  _  s  i  z  e  01 0  14 00 00 q  \f t  h  r  e  a
0d60 d  _  s  t  a  c  k  06 1  9  6  6  0  8  1d 00 00 r  \f t  x  _  i  s  o  l  a  t  i  o  n  0f
0d80 R  E  P  E  A  T  A  B  L  E  -  R  E  A  D  0e 00 00 s  \b t  i  m  e  z  o  n  e  04 C  E  S
0da0 T  18 00 00 t  0e t  m  p  _  t  a  b  l  e  _  s  i  z  e  \b 3  3  5  5  4  4  3  2  \r 00 00
0dc0 u  06 t  m  p  d  i  r  05 /  t  m  p  /  1c 00 00 v  07 v  e  r  s  i  o  n  13 4  .  0  .  1
0de0 2  -  s  t  a  n  d  a  r  d  -  l  o  g  13 00 00 w  \f w  a  i  t  _  t  i  m  e  o  u  t  05
0e00 2  8  8  0  0  01 00 00 x  þ  <font color="red">11 00 00 00 03 S  E  T     a  u  t  o  c  o  m  m  i  t  =  1</font>  03
0e20 00 00 01 00 00 00 <b>
                     <font color="red">18 00 00 00 03 S  E  L  E  C  T     *     F  R  O  M     E  M  P  L  O  Y  E</font>
                  </b>
0e40 <b>
                     <font color="red">E  ;</font>  01 00 00 01 \n 19 00 00 02 \b E  M  P  L  O  Y  E  E  05 F  N  A  M  E  03 \n 00 00 01 ý</b>
0e60 <b>03 01 00 00 19 00 00 03 \b E  M  P  L  O  Y  E  E  05 M  I  N  I  T  03 01 00 00 01 þ  03 00 00</b>
0e80 <b>00 19 00 00 04 \b E  M  P  L  O  Y  E  E  05 L  N  A  M  E  03 \n 00 00 01 ý  03 01 00 00 17 00</b>
0ea0 <b>00 05 \b E  M  P  L  O  Y  E  E  03 S  S  N  03 \t 00 00 01 03 03 01 00 00 19 00 00 06 \b E  M</b>
0ec0 <b>P  L  O  Y  E  E  05 B  D  A  T  E  03 \n 00 00 01 \n 03 00 00 00 1b 00 00 07 \b E  M  P  L  O</b>
0ee0 <b>Y  E  E  07 A  D  D  R  E  S  S  03 1e 00 00 01 ý  03 00 00 00 17 00 00 \b \b E  M  P  L  O  Y</b>
0f00 <b>E  E  03 S  E  X  03 01 00 00 01 þ  03 00 01 00 1a 00 00 \t \b E  M  P  L  O  Y  E  E  06 S  A</b>
0f20 <b>L  A  R  Y  03 07 00 00 01 05 03    00 02 1c 00 00 \n \b E  M  P  L  O  Y  E  E  \b S  U  P  E</b>
0f40 <b>R  S  S  N  03 \t 00 00 01 03 03 00 00 00 17 00 00 0b \b E  M  P  L  O  Y  E  E  03 D  N  O  03</b>
0f60 <b>01 00 00 01 03 03 00 00 00 01 00 00 \f þ  R  00 00 \r 04 J  o  h  n  01 B  05 S  m  i  t  h  \t</b>
0f80 <b>1  2  3  4  5  6  7  8  9  \n 1  9  6  5  -  0  1  -  0  9  18 7  3  1     F  o  n  d  r  e  n</b>
0fa0 <b>,     H  o  u  s  t  o  n  ,     T  X  01 M  \b 3  0  0  0  0  .  0  0  \t 3  3  3  4  4  5  5</b>
0fc0 <b>5  5  01 5  R  00 00 0e \b F  r  a  n  k  l  i  n  01 T  04 W  o  n  g  \t 3  3  3  4  4  5  5</b>
0fe0 <b>5  5  \n 1  9  5  5  -  1  2  -  0  8  15 6  3  8     V  o  s  s  ,     H  o  u  s  t  o  n  ,</b>
1000 <b>   T  X  01 M  \b 4  0  0  0  0  .  0  0  \t 8  8  8  6  6  5  5  5  5  01 5  T  00 00 0f 06 A</b>
1020 <b>l  i  c  i  a  01 J  06 Z  e  l  a  y  a  \t 9  9  9  8  8  7  7  7  7  \n 1  9  6  8  -  0  7</b>
1040 <b>-  1  9  17 3  3  2  1     C  a  s  t  l  e  ,     S  p  r  i  n  g  ,     T  X  01 F  \b 2  5</b>
1060 <b>0  0  0  .  0  0  \t 9  8  7  6  5  4  3  2  1  01 4  W  00 00 10 \b J  e  n  n  i  f  e  r  01</b>
1080 <b>S  07 W  a  l  l  a  c  e  \t 9  8  7  6  5  4  3  2  1  \n 1  9  4  1  -  0  6  -  2  0  17 2</b>
10a0 <b>9  1     B  e  r  r  y  ,     B  e  l  l  a  i  r  e  ,     T  X  01 F  \b 4  3  0  0  0  .  0</b>
10c0 <b>0  \t 8  8  8  6  6  5  5  5  5  01 4  V  00 00 11 06 R  a  m  e  s  h  01 K  07 N  a  r  a  y</b>
10e0 <b>a  n  \t 6  6  6  8  8  4  4  4  4  \n 1  9  6  2  -  0  9  -  1  5  18 9  7  5     F  i  r  e</b>
1100 <b>   O  a  k  ,     H  u  m  b  l  e  ,     T  X  01 M  \b 3  8  0  0  0  .  0  0  \t 3  3  3  4</b>
1120 <b>4  5  5  5  5  01 5  S  00 00 12 05 J  o  y  c  e  01 A  07 E  n  g  l  i  s  h  \t 4  5  3  4</b>
1140 <b>5  3  4  5  3  \n 1  9  7  2  -  0  7  -  3  1  16 5  6  3  1     R  i  c  e  ,     H  o  u  s</b>
1160 <b>t  o  n  ,     T  X  01 F  \b 2  5  0  0  0  .  0  0  \t 3  3  3  4  4  5  5  5  5  01 5  S  00</b>
1180 <b>00 13 05 A  h  m  a  d  01 V  06 J  a  b  b  a  r  \t 9  8  7  9  8  7  9  8  7  \n 1  9  6  9</b>
11a0 <b>-  0  3  -  2  9  17 9  8  0     D  a  l  l  a  s  ,     H  o  u  s  t  o  n  ,     T  X  01 M</b>
11c0 <b>\b 2  5  0  0  0  .  0  0  \t 9  8  7  6  5  4  3  2  1  01 4  G  00 00 14 05 J  a  m  e  s  01</b>
11e0 <b>E  04 B  o  r  g  \t 8  8  8  6  6  5  5  5  5  \n 1  9  3  7  -  1  1  -  1  0  16 4  5  0</b>
1200 <b>S  t  o  n  e  ,     H  o  u  s  t  o  n  ,     T  X  01 M  \b 5  5  0  0  0  .  0  0  û  01 1</b>
1220 <b>01 00 00 15 þ</b>
               </span>
            </pre>
         </code>
         <p>Die Analyse des Datenverkehrs zeigt, daß im Falle der JDBC-basierten Kommunikation
        ein gegenüber der nativen Schnittstelle um 3529 Byte vergrößertes Datenaufkommen ausgetauscht wird.
        Diese zusätzliche Datenmenge fällt jedoch nur einmal zum Zeitpunkt des JDBC-Verbindungsaufbaus statisch an.
        (<a href="JDBCDoubleSelect.hex">Vgl. Mitschnitt der mehrfachen Ausführung einer SQL-Anfrage innerhalb einer
        bestehenden JDBC-Verbindung</a>)<br/>
        Zusätzlich offenbart Zeile 0x40 des Datenverkehrs die verschlüsselte Übermittlung des Paßwortes des
        Anwenders <em>mario</em>. Allerdings werden die per Anfrage ermittelten Nutzdaten (ab Zeile 0xe40) unverschlüsselt
        über die Netzwerkschnittstelle übertragen und stellen somit ein potentielles Angriffsziel dar.<br/>
        Abhilfe hierfür kann die Tunnelung des Datenverkehrs, beispielsweise mittels
        <a href="http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci214091,00.html" external="yes">SSH</a>,
        durch eine sichere Verbindung bieten.</p>
         <scriptElement type="links" title="Weiterführende Links">
            <link>
               <a href="http://java.sun.com/products/jdbc">JDBC
            @ SUN</a>
            </link>
            <link>
               <a href="http://java.sun.com/products/jdbc/learning.html">JDBC learning center @ SUN</a>
            </link>
            <link>
               <a href="http://java.sun.com/docs/books/tutorial/jdbc/jdbc2dot0/inserting.html">JDBC
            Tutorial</a>
            </link>
            <link>
               <a href="http://www.jguru.com/faq/JDBC">JDBC FAQ
            @ JGuru.com</a>
            </link>
            <link>
               <a href="http://www.oreilly.com/catalog/javadata/">G.
            Reese: <em>Database Programming with JDBC and
            Java</em>. O'Reilly, 1997</a>
            </link>
            <link>
               <a href="http://www.ddj.com/documents/s=953/ddj9613a/9613a.htm">Verhältnis
            von X/Open CLI und ODBC</a>
            </link>
         </scriptElement>
      </span>
      <subtopic name="ejb">1.2 Enterprise Java Beans</subtopic>
      <span xml:base="file:/I:/development/vorlesung/sharedScriptParts/EJB2.xml">
         <p>Neben den bereits aus anderen Veranstaltungen bekannten Servlets und den davon abgeleiteten Java Server Pages bildet die Technik der         <em>Enterprise Java Beans</em> (EJB) einen weiteren zentralen Baustein der Java 2 Enterprise Plattform.         Als serverseitige Komponenten kommt den EJBs heute große Bedeutung in der Realisierung komplexer         Anwendungen, insbesondere durch Umsetzung der sog. <gerquot>Business Logik</gerquot>, d.h. den nicht-interaktiven         fachlichen Anwendungsteilen, zu.</p>
         <p>Der Begriff der Enterprise Java Bean stützt sich auf dem historisch älteren der <em>
               <a href="http://developer.java.sun.com/developer/onlineTraining/Beans/Beans1/simple-definition.html ">Java Bean</a>
            </em>. Eine solche stellt eine abgeschlossene wiederverwendbare Softwarekomponente dar, die nach ihrer Erstellung über festgelegte Schnittstellen parametrisiert und manipuliert werden kann. Hierzu muß eine Bean eine festgelegte Interaktionsschnittstelle bieten, die durch die Java Bean Spezifikation definiert ist. Es handelt sich dabei um eine Reihe von Konventionen, der eine Bean gehorchen muß, jedoch um keine festgelegte API, die durch eine Komponente zu implementieren ist.<br/> Der Begriff der Enterprise Java Bean greift diese inhaltliche Fundierung auf und präzisiert gleichzeitig die technische Umsetzung. So stellt eine Enterprise Java Bean eine Softwarekomponente dar, die in einer festgelegten Ausführungsumgebung, welche durch die EJB-Spezifikation festgelegte Dienste zur Nutzung durch die Beans anbieten kann. Eine solche Ausführungsumgebung wird als <em>Container</em> bezeichnet.<br/> Ziel der Trennung in Komponente und Ausführungsumgebung ist die Zielsetzung, die Enterprise Java Bean ausschließlich zur Umsetzung fachlicher Aufgaben heranzuziehen und alle infrastrukturellen Fragestellungen wie Betriebsmittelverwaltung,  Persistenz oder Sicherheit durch die Ausführungsumgebung in gleicher Weise für alle Komponenten bereitzustellen.<br/> Ein EJB-Container wird zumeist im Rahmen eines Application-Servers bereitgestellt.<br/> Die gelegentlich anzutreffende Hervorhebung der anfänglich für Java Beans intendierten <em>visuellen Manipulationsmöglichkeit</em> trifft für Enterprise Java Beans nicht zu und hat sich für Java Beans auch nur begrenzte Bedeutung erlangt. </p>
         <p>Spezifikationsgemäß können EJB-Container folgende Eigenschaften offerieren:</p>
         <ul>
            <li>
               <b>Betriebsmittelverwaltung</b>
               <br/>     Typischerweise verwaltet ein einziger EJB-Container gleichzeitig eine Reihe verschiedener Enterprise Java     Beans. Zur Organisation und Aufrechterhaltung der Ausführbarkeit obliegt dem Container die Zuteilung von     Betriebsmitteln wie Hauptspeicher, CPU-Zeit oder Netzwerkressourcen an die verwalteten EJB. Hierunter     fällt insbesondere auch die Einlagerung, Instanziierung und Entfernung der EJBs selbst.</li>
            <li>
               <b>Zustandsverwaltung</b>
               <br/>     In praktischen Anwendungen ist oft die Nutzung zustandsbehafteter Kommunikation, die sich über verschiedene     Einzelinteraktionen erstreckt gewünscht. Die hierfür notwendigen technischen Voraussetzungen (Zustandsspeicherung,     Korrelation der Einzelinteraktionen) werden durch den Container bereitgestellt.</li>
            <li>
               <b>Transaktionsverwaltung</b>
               <br/>     Erweiterung der Zustandsverwaltung. Zur Gewährleistung des benötigten Verhaltens müssen EJBs keine eigenen     Implementierungen zur Verfügung stellen, sondern können vorhandene Dienste des Containers nutzen.</li>
            <li>
               <b>Sicherheit</b>
               <br/>     Die Sicherheit von EJBs kann durch Vergabe von Zugriffsrechten und Rollen auf Containerebene gesteuert werden.</li>
            <li>
               <b>Persistenz</b>
               <br/>     Der interne Zustand einer verwalteten EJB kann wahlfrei in persistiert und zu einem späteren Zeitpunkt wiederhergestellt     werden.</li>
            <li>
               <b>Entfernter Zugriff</b>
               <br/>     Der Zugriff auf EJBs erfolgt mittels <a href="http://www.jeckle.de/vorlesung/eBusinessEng/script.html#RMI">Remote Method Invocation</a> und ist daher Lokationstransparent.</li>
         </ul>
         <p>Neben den in der Aufzählung dargestellten Eigenschaften dürfen Container zusätzlich Weitere wahlfrei implementieren.</p>
         <subsubtopic name="EJBTypen">EJB-Typen</subsubtopic>
         <p>Grundsätzlich lassen sich alle EJBs drei Typen zuordnen: <em>Session Beans</em>, <em>Entity Beans</em> und <em>Message Driven Beans</em>. Während erstere hauptsächlich zur Abbildung von Abläufen eingesetzt werden, dienen Entity Beans der Abwicklung von Zugriffen auf Daten. Eine Sonderstellung nehmen die <em>Message Driven Beans</em> ein, die lediglich hinsichtlich ihres Kommunikationsverhaltens festgelegt sind.</p>
         <p>
            <b>Session Beans</b> dienen der Abbildung von Abläufen im Rahmen der Programmierung der sog. Business Logik. Die Lebensdauer (d.h. Zeitspanne zwischen Erzeugung im und Entfernung aus dem Hauptspeicher) ist daher identisch mit der einer durch den Client erfolgenden Anfrage. Jede zu einem Zeitpunkt existierende Session Bean repräsentiert daher eine zugehörige Clientinstanz.<br/> Nach ihrer internen Ausgestaltung werden <em>stateless</em> und <em>statefull</em> Session Beans unterschieden. Während Erstere keinen über einen einzigen Aufruf hinausgehenden Zustand verwalten und daher seiteneffektfrei lediglich auf den durch den Aufruf übermittelten Daten operieren erhält das zustandserhaltende Pendant die Daten eines Aufrufs und kann diese auch in nachfolgenden Aufrufen verarbeiten.</p>
         <p>
            <b>Entity Beans</b> sind programmiersprachliche Stellvertreter datenbankresidenter Objekte. Sie dienen dem erleichterten Zugriff auf persistent vorliegende Datenbestände. Ihre interne Realisierung ist eng mit der Technik relationaler Datenbankmanagement System verbunden. So werden Sie durch einen anwenderdefinierten <a href="../datenbanken/script.html#Primaerschluessel">Primärschlüssel</a> dauerhaft identifiziert.</p>
         <p>
            <b>Message Driven Beans</b> sind hinsichtlich ihres Kommunikationsverhaltens auf asynchrone Aufrufe beschränkt. Die Realisierung des eigentlichen Verhaltens wird durch eine Ausprägung eines der anderen Beantypen geboten.</p>
         <subsubtopic name="EJBSB">Session Beans</subsubtopic>
         <p>Konzeptionell umfaßt jede EJB-Anwendung, die Session Beans einsetzt, die in  <illustrationLink ref="SLEJB"/>  dargestellten Teile:</p>
         <ul>
            <li>Implementierung der EJB selbst.</li>
            <li>
               <em>Remote</em>-Schnittstelle zum Zugriff auf die durch die Bean publizierten Methoden.</li>
            <li>
               <em>Home</em>-Schnittstelle zur Ermittlung einer Referenz auf das Bean-Objekt.</li>
         </ul>
         <illustration id="SLEJB" width="550" caption="Aufrufstruktur einer zustandslosen EJB" gfx="ebe/ejbAufruf.gif"/>
         <p>Gegenüber der Realisierung als RMI-Anwendung benötigt die Umsetzung als zustandslose Session Bean die Erstellung einer sog. <gerquot>Home-Schnittstelle</gerquot> (<em>Home Interface</em>), welche die Operation <code>create</code> zur Instanziierung des serverseitigen EJB-Objekts bietet.<br/> Sie ist im Beispiel <scriptRef type="example" name="EJBHomeInterf"/> dargestellt.</p>
         <scriptElement type="example" name="EJBHomeInterf" title="Home-Schnittstelle einer EJB" filename="SayHelloHome.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/SayHelloHome.java"/>
         </scriptElement>
         <p>Die anwenderdefinierte Home-Schnittstelle erweitert die durch die Standard-API vorgegebene Schnittstelle <code>EJBHome</code>. Diese definiert Operationen zur Entfernung existierender EJB-Objekte aus dem Hauptspeicher (<code>remove</code>) sowie zur Ermittlung von Metadaten (<code>getEJBMetaData</code>) oder zum Erhalt eines netzwerkunabhängigen Verweises auf das EJB-Objekt (<code>getHomeHandle</code>).<br/> Im Einzelnen sind dies die Operationen:</p>
         <ul>
            <li>
               <code>EJBMetaData getEJBMetaDate()</code>
               <br/>     Liefert ein <code>EJBMetaData</code>-Objekt welches einzelne Eigenschaften einer EJB näher beschreibt. Hierzu zählen:     <ul>
                  <li>Klasse der Home-Schnittstelle</li>
                  <li>Klasse des Primärschlüssels (nur vorhanden sofern es sich um eine Entity Bean handelt)</li>
                  <li>Klasse der Remote-Schnittstelle</li>
                  <li>
                     <name>Boole</name>'scher Wert, der angibt, ob es sich um eine Session Bean handelt</li>
                  <li>
                     <name>Boole</name>'scher Wert, der angibt, ob es sich um eine zustandslose Session Bean handelt</li>
               </ul>
            </li>
            <li>
               <code>HomeHandle getHomeHandle()</code>
               <br/>     Liefert ein Objekt des Typs <code>HomeHandle</code> zurück, welches eine netzwerkunabhängige Abstraktion des     Verweises auf das Home-Objekt realisiert.</li>
            <li>
               <code>void remove (Handle h)</code>
               <br/>     Entfernt ein durch den Objektverweis (<code>Handle</code>) identifiziertes EJB-Objekt aus dem Hauptspeicher.</li>
            <li>
               <code>void remove (Object pk)</code>
               <br/>     Entfernt ein durch das übergebene Primärschlüsselobjekt identifiziertes EJB-Objekt aus dem Hauptspeicher.</li>
         </ul>
         <p>Interessanterweise definiert die Schnittstelle zwar Operationen zur Ermittlung von Daten über bestehende Objekte und zur Entfernung dieser Objekte aus dem Hauptspeicher, nicht jedoch zu ihrer Erzeugung.<br/> Dies liegt in der durch die Programmiersprache Java angestrebten statischen Typsicherheit begründet, die es nicht gestattet Operationen mit variablen Parameterlisten --- wie sie für die zum API-Erstellungszeitpunkt unbekannten spezifischen Initialisierungsparameter aller denkbaren EJBs benötigt würden --- zu versehen.<br/> Aus diesem Grunde definiert die EJB-Spezifikation informell, daß ein diese Schnittstelle erweiternde eigene Home-Schnittstelle zusätzlich die Methode <code>create</code>, deren Signatur als Rückgabetyp den Typ der Remote-Schnittstelle vorsehen muß definiert. Zusätzlich enthält diese Operation die zur Initialisierung der Bean benötigten Parameter in ihrer Parameterliste.</p>
         <p>Die im Beispiel <scriptRef type="example" name="EJBRemInterf"/> ist Remote-Schnittstelle dargestellt, deren Ausprägungen von Home-Objekten angesprochenen werden:</p>
         <scriptElement type="example" name="EJBRemInterf" title="Remote-Schnittstelle einer EJB" filename="SayHello.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/SayHello.java"/>
         </scriptElement>
         <p>Schnittstellen dieses Typs enthalten ausschließlich die fachlichen Operationen, d.h. die Signaturen der Methoden, die später durch den Client benutzt werden.<br/>
            <a name="EJBObjEig">Jede</a> Remote-Schnittstelle erweitert zusätzlich die vorgegebene Schnittstelle <code>EJBObject</code>, welche, ähnlich zur Home-Schnittstelle, einige Operationen zur Verwaltung eines EJB-Objektes vorgibt:</p>
         <ul>
            <li>
               <code>EJBHome getEJBHome()</code>
               <br/>     Liefert die Home-Schnittstelle einer EJB.</li>
            <li>
               <code>Handle getHandle()</code>
               <br/>     Liefert ein Objekt des Typs <code>HomeHandle</code> zurück, welches eine netzwerkunabhängige Abstraktion des     Verweises auf das Home-Objekt realisiert.</li>
            <li>
               <code>Object getPrimaryKey()</code>
               <br/>     Liefert das Primärschlüsselobjekt einer Entity Bean.</li>
            <li>
               <code>boolean isIdentical(EJBObject eo)</code>
               <br/>     Prüft ob das übergebene EJB-Objekt dasselbe wie das Objekt ist auf dem die Methode ausgeführt wird.</li>
            <li>
               <code>void remove()</code>
               <br/>     Entfernt das EJB-Objekt aus dem Bean-Container.</li>
         </ul>
         <p>Beispiel <scriptRef type="example" name="SLSessionBean"/> zeigt die Implementierung der Bean selbst:</p>
         <scriptElement type="example" name="SLSessionBean" title="Realisierung einer Session Bean" filename="HelloWorldBean.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/HelloWorldBean.java"/>
         </scriptElement>
         <p>Die programmiersprachliche Umsetzung der Bean enthält die Methoden der in der Remote-Schnittstelle bekanntgegebenen fachlichen Operationen. Zusätzlich muß ein Konstruktur expliziert werden, dessen Parameterliste mit den für die Operation <code>create</code> des Home-Interfaces gegebenen übereinstimmen.<br/> Spezifikationsgemäß muß jede Session Bean die gleichnamige API-Schnittstelle implementieren. Diese definiert einige Operationen zur Behandlung unterschiedlicher Lebenszyklusstadien einer EJB. Hierunter fallen Methoden, die beim Erzeugen (<code>ejbCreate</code>), Entfernen (<code>ejbRemove</code>), bei der Passivierung (d.h. Auslagerung auf Hintergrundspeicher) (<code>ejbPassivate</code>) und dessen Reaktivierung (<code>ejbActivate</code>) eines EJB-Objekts durch die Ausführungsumgebung aufgerufen werden.</p>
         <p>Bei der zwingend zu implementierenden Schnittstelle <code>SessionBean</code> handelt es sich nicht nur um eine Konvention um die Umsetzung der Lebenszyklusschnittstelle sicherzustellen, sondern auch um die Kategorisierung der Bean selbst. So stellt die im Beispiel verwandte Schnittstelle <code>SessionBean</code> neben <code>EntityBean</code> und <code>MessageDrivenBean</code> eine Spezialisierung der (operationslosen) Schnittstelle <code>EnterpriseBean</code> dar, deren <gerquot>Implementierung</gerquot> durch eine Klasse lediglich zur Kennzeichnung dieser als EJB herangezogen wird.<br/> Die genannten Spezialisierungen dieser Schnittstelle erfüllen daher sowohl den Zweck der Ausübung des Implementierungszwanges für die in ihnen aufgeführten Operationen als auch den der typisierenden Kennzeichnung.<br/> Darüberhinaus ist <code>EnterpriseBean</code> als Spezialisierung der Standard-Schnittstelle <a offset="java/io/Serializable.html" fixedType="JDK14" keyword="yes">Serializable</a> angelegt. In der Konsequenz muß jedes EJB-Objekt durch die Javasprachmechnismen serialisierbar sein. Diese Eigenschaft wird insbesondere für die Passivierung und im Rahmen der Entity Beans genutzt.</p>
         <p>Konzeptionell erinnert die Trennung in publizierte fachliche Schnittstelle (Remote-Schnittstelle) und deren technischer Umsetzung durch die EJB an die aus der Betrachtung des Remote Method Invocation Mechanismus bekannte Struktur.<br/> Allerdings weicht die Umsetzung der Bean von der dort anzutreffenden Konvention ab, die publizierte Schnittstelle selbst durch die realisierende Klasse zu implementieren. Dies liegt vor allem an der gegenüber RMI veränderten Struktur der publizierten Schnittstelle begründet. Während RMI für die Schnittstelle die Spezialisierung der operationslosen Standardschnittstelle <a fixedType="JDK14" offset="java/rmi/Remote.html" keyword="yes">Remote</a> fordert die EJB-Spezifikation die Erweiterung der Schnittstelle <a fixedType="J2EE13" offset="javax/ejb/EJBObject.html" keyword="yes">EJBObject</a>, welche selbst die <a href="#EJBObjEig">oben dargestellten</a> Operationen definiert. Aus diesem Grunde würde die Aufnahme der Remote-Schnittstelle, obwohl konzeptionell durchaus zu rechtfertigen, in die Umsetzungsliste der EJB gleichzeitig die Implementierung von zumindest leeren Methodenrümpfen für die in <code>EJBObject</code> definierten Operationen notwendig werden lassen.<br/> Abgesehen von dieser Ausnahme rekonstruiert das Verhältnis zwischen EJB und deren Remote-Schnittstelle die aus RMI bekannte Beziehung zwischen Schnittstelle und Umsetzung.</p>
         <p>Die Nutzung einer durch eine Java Bean angebotenen Funktionalität erfolgt gemäß dem in <illustrationLink ref="SLEJB"/> dargestellten Schema. Ein dies umsetzender Client ist in Beispiel <scriptRef type="example" name="SLSBClient"/> dargestellt.</p>
         <scriptElement type="example" name="SLSBClient" title="Zugriff auf eine Session Bean" filename="CallHelloWorldBean.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/CallHelloWorldBean.java"/>
         </scriptElement>
         <p>Zunächst ermittelt der Client unter Nutzung der JNDI-API eine Referenz auf die EJB. Dies geschieht durch Anfrage (lookup) an den JNDI-Dienst unter Übergabe des bekannten Klarnamens (<em>helloBean</em>).<br/> Die erhaltene generische Referenz wird durch Aufruf der statischen Methode <a fixedType="JDK14" offset="javax/rmi/PortableRemoteObject.html#narrow(java.lang.Object, java.lang.Class)" keyword="yes">narrow</a> der Klasse <a fixedType="JDK14" offset="javax/rmi/PortableRemoteObject.html" keyword="yes">PortableRemoteObject</a> typsicher in eine Ausprägung der Home-Schnittstelle konvertiert.<br/> Der Aufruf der in dieser Schnittstelle durch den Anwender definierten <code>create</code>-Methode sorgt für die serverseitige Instanziierung der EJB, die als Ausprägung der Remote-Schnittstelle geliefert wird. Tatsächlich wird nicht das EJB-Objekt selbst durch den Methodenaufruf retourniert, sondern lediglich ein netzwerktransparenter Verweis darauf, der jedoch clientseitig einer lokalen Objektreferenz gleichgestellt verwendet werden kann.<br/> Ferner wird serverseitig zur Kommunikation mit der EJB ein Home-Objekt erzeugt, welchem eine Stellvertreterrolle für den anfragenden Client zukommt.<br/> Der Aufruf der durch die EJB zur Verfügung gestellten Methode erfolgt identisch zu dem einer Lokalen.</p>
         <subsubtopic name="EJBEB">Entity Beans</subsubtopic>
         <p>Die zweite zentrale Klasse von Enterprise Java Beans bilden die zur serverseitigen Persistierung von Objekten dienenden <em>Entity Beans</em>.<br/> Sie kapseln Datenbankinhalte durch Objekte, die gemäß der EJB-Spezifikation instanziierbar und zugreifbar sind. Die Verwaltung der gekapselten Dateninhalte erfolgt durch ein frei festlegbares Datenbankmanagementsystem, die der Objekte selbst durch den EJB-Container.<br/> Ziel dieser Technik ist es die Komplexität der Persistenzlogik für den Verwender der bereitgestellten Bean vollkommen transparent zu gestalten und serverseitig zu realisieren.<br/> Die Familie der Entity Beans selbst zerfällt in zwei Untertypen, welche sich entlang des Realisierungspunktes der Persistenzlogik separieren: <em>Bean Managed Persistence</em>, der Bean obliegt die Umsetzung der Persistenzlogik, und <em>Container Managed Persistence</em>, hierbei wird die Persistenzlogik durch den EJB-Container realisiert.</p>
         <p>Das nachfolgende Beispiel zeigt die Umsetzung einer Entity Bean mit Bean Managed Persistence. Es kapselt die Verwaltung und den Zugriff auf Objekte, die Personen beschreiben. Jedes <code>Person</code>en-Objekt enthält Daten zu Name, Geburtsdatum und Wohnstraße. Der Name dient als eindeutige Identifikation und daher datenbankseitig als Primärschlüssel. Die notwendige Datenbanktabelle wurde erzeugt durch den SQL-Ausdruck: <code>
               <pre>CREATE TABLE PERSON( Name VARCHAR(20) PRIMARY KEY, Birthdate DATE, Street VARCHAR(30));</pre>
            </code>
         </p>
         <p>Wie bereits für die Realisierung von Session Beans eingeführt, werden auch zur Publikation der extern zugänglichen Schnittstellen Home und Remote Interfaces benötigt.</p>
         <p>Struktur und Aufbau der Home-Schnittstelle ähnelt konzeptionell der für Session Beans eingeführten. Dieser Schnittstellentyp dient auch für Entity Beans zur Aufnahme der Verwaltungsoperationen zur Erzeugung (<code>create</code>) und zur Suche existierender EJBs (<code>findByPrimaryKey</code>).<br/> Beispiel <scriptRef type="example" name="EEJBHome"/> zeigt die Home-Schnittstelle des Beispiels.</p>
         <scriptElement type="example" name="EEJBHome" title="Home-Schnittstelle einer Entity Bean" filename="PersonHome.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/PersonHome.java"/>
         </scriptElement>
         <p>Die Home-Schnittstelle zeigt die <code>create</code>-Operation zur Erzeugung einer neuen EJB-Instanz. Ihre Übergabeparameter dienen zur Konstruktion des neuen Objekts und werden durch die Bean-Implementierung interpretiert.<br/> Ferner enthält die Schnittstelle mit <code>findByPrimaryKey</code> eine Operation, deren Implementierung eine Entity-Bean anhand ihres Primärschlüssels identifiziert und liefert. Aus diesem Grunde erhält die Methode den zu suchenden Wert vom Typ des Primärschlüssels übergeben.<br/> Hinsichtlich der verwendeten Typen zeigt sich bereits hier, daß eine Abbildung der durch die Programmiersprache Java bereitgestellten Typen auf die des eingesetzten Persistenzsystems stattfinden muß. In der im Beispiel gewählten Ausführungsform der durch die EJB selbst verwalteten Persistenz muß diese Abbildung manuell durch den Programmierer bereitgestellt werden.</p>
         <p>Die Remote-Schnittstelle gibt die für Nutzer der Bean zugänglichen Geschäftsfunktionen wieder. Daher enthält dieser Schnittstellentyp lediglich Operationen zum Zugriff auf die verwalteten Daten, nicht jedoch zur technischen Verwaltung und Interaktion mit dem Bean-Container.<br/> Per Konvention muß diese Schnittstelle als Spezialisierung der Schnittstelle <a fixedType="J2EE13" offset="javax/ejb/EJBObject.html" keyword="yes">EJBObject</a> definiert sein. Diese Standardschnittstelle definiert allgemeine Interaktionsformen, wie Löschen (<code>remove</code>), Vergleich (<code>isIdentical</code>) und Ermittlung des Primärschlüsselwertes (<code>getPrimaryKey</code>) die für alle Entity Bean Objekte gleichermaßen benötigt werden.<br/>
            <a offset="javax/ejb/EJBObject.html#isIdentical(javax.ejb.EJBObject)" fixedType="J2EE13" keyword="yes">isIdentical</a> liefert den Vergleich zweier serverseitiger EJB-Objekte und ermittelt so, ob zwei Java-Objektreferenzen auf dasselbe Datenbankobjekt zugreifen.<br/>
            <a fixedType="J2EE13" offset="javax/ejb/EJBObject.html#getPrimaryKey()" keyword="yes">getPrimaryKey</a> ermittelt den Wert des Primärschlüssels eines gegebenen EJB-Objekts aus der Datenbank.<br/> Zur Lösung von datenbankresidenten Objekten wird <a fixedType="J2EE13" offset="javax/ejb/EJBObject.html#remove()" keyword="yes">remove</a> eingesetzt. Der Aufruf dieser Methode entfernt ausschließlich die durch die EJB repräsentierten Datenbanktupel, die programmiersprachliche Objektrepräsentation bleibt jedoch über die gesamte Laufzeit (sofern nicht durch Gültigkeitsbereiche oder explizite <code>NULL</code>-Setzung explizit anders gehandhabt) intakt.</p>
         <scriptElement type="example" name="EEJBRemote" title="Remote-Schnittstelle einer Entity Bean" filename="Person.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/Person.java"/>
         </scriptElement>
         <p>Beispiel <scriptRef type="example" name="EEJBBean"/> zeigt den vollständigen Code der Bean. Sie implementiert mit <a fixedType="J2EE13" offset="javax/ejb/EntityBean.html" keyword="yes">EntityBean</a> die Standardschnittstelle aller Entity Beans, welche als Spezialisierung der ausschließlich markierenden Schnittstelle <a fixedType="J2EE13" offset="javax/ejb/EnterpriseBean.html" keyword="yes">EnterpriseBean</a> die notwendigen Basisoperationen zur Abwicklung der persistenten Speicherung bieten.</p>
         <p>Im Falle einer <em>Bean Managed Persistence</em> enthalten die Methoden der durch die Schnittstelle definierten und der zusätzlich im Rahmen der Spezifikation textuell definierten Operationen die notwendigen Aufrufe zur Ablage eines Objekts in der Datenbank und zu seiner späteren Extraktion daraus.<br/> Im Einzelnen sind dies die Operationen:</p>
         <scriptElement type="table" name="EEJBOperationen" title="Persistenzoperationen einer Entity Bean">
            <table border="1">
               <tr>
                  <td style="text-align:center;">
                     <b>
                        <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Operation</span>
                     </b>
                  </td>
                  <td style="text-align:center;">
                     <b>
                        <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Semantik</span>
                     </b>
                  </td>
                  <td style="text-align:center;">
                     <b>
                        <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Zugehörige SQL-Anweisung</span>
                     </b>
                  </td>
               </tr>
               <tr>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>ejbCreate</code>
                     </span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Wird nach dem Erzeugen eines Java-Objektes aufgerufen um dieses in der Datenbank abzulegen.<br/>                     Diese Operation ist nicht Bestandteil der Schnittstelle, da ihre Parameter, die den Übergabeparametern des                     Objektkonstruktors entsprechen, zum Schnittstellenerzeugungszeitpunkt                     nicht feststehen.</span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>INSERT</code>
                     </span>
                  </td>
               </tr>
               <tr>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>ejbFindByPrimaryKey</code>
                     </span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Liefert den Wert des Primärschlüssels zurück, sofern ein Datenbankeintrag                     existiert, der durch diesen Primärschlüssel identifiziert wird.<br/>                     Diese Operation ist nicht Bestandteil der Schnittstelle, da ihre Parameter, die                     in Typ, Name und Reihenfolge der Zusammensetzung des                     Primärschlüssels entsprechen, zum Schnittstellenerzeugungszeitpunkt                     nicht feststehen.<br/>                     Diese Methode wird nicht durch den Anwender direkt aufgerufen, sondern stattdessen                     auf einer Ausprägung der Home-Schnittstelle das dort zur Verfügung stehende Analogon                     <code>findByPrimaryKey</code>, welches das durch den Primärschlüssel identifizierte EJB-Objekt                     zurückliefert. Diese Methode greift intern auf ausschließlich den Schlüssel liefernde Methode                     der Bean zu.</span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>SELECT</code>
                     </span>
                  </td>
               </tr>
               <tr>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>
                           <a fixedType="J2EE13" offset="javax/ejb/EntityBean.html#ejbRemove()" keyword="yes">ejbRemove</a>
                        </code>
                     </span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Entfernt das EJB-Objekt aus der Datenbank.</span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>DELETE</code>
                     </span>
                  </td>
               </tr>
               <tr>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>
                           <a fixedType="J2EE13" offset="javax/ejb/EntityBean.html#ejbStore()" keyword="yes">ejbStore</a>
                        </code>
                     </span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">Synchronisiert das Java-Objekt mit dem EJB-Objekt und aktualisiert so die Datenbankinhalte.<br/>                     Diese Methode wird nach jedem Zugriff mittels einer in der Remote-Schnittstelle                     aufgeführten Operation auf das EJB-Objekt ausgeführt.</span>
                  </td>
                  <td>
                     <span style="font-family:Verdana,Arial,Geneva, sans-serif;">
                        <code>UPDATE</code>
                     </span>
                  </td>
               </tr>
            </table>
         </scriptElement>
         <scriptElement type="example" name="EEJBBean" title="Eine Entity Bean" filename="PersonBean.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/PersonBean.java"/>
         </scriptElement>
         <p>Zusätzlich enthält die Bean des Beispiels mit <code>getAge</code> eine zwar in der Remote-Schnittstelle veröffentlichte Operation, die keinen direkt abgespeicherten Wert liefert, sondern diesen dynamisch zur Ausführungszeit anhand der verfügbaren Daten berechnet.</p>
         <p>Alle anderen in der Remote-Schnittstelle aufgeführten Operationen (etwa: <code>getStreet</code>, <code>setStreet</code>) modifizieren lediglich, den durch die Attribute repräsentierten Java-Objektzustand und greifen nicht direkt auf die Datenbank zu.</p>
         <p>Innerhalb der Datenbankzugreifenden Methoden muß durch den Anwender die Abbildung der Java-Datentypen auf die des verwendeten Datenbankmanagementsystems erfolgen. Die mit dem Präfix <code>ejb</code> versehenden Methoden zeigen dies für die lesenden und schreibenden DB-Zugriffe. So kann die im Beispiel für <code>name</code> und <code>street</code> verwendete Java-Repräsentation <code>String</code> vergleichsweise leicht in den SQL-Typ <code>VARCHAR</code> abgebildet werden, sofern alle Methoden, die Datenbankinhalte schreiben, sicherstellen, daß nur zum Datenbankschema konforme Werte eingefügt werden. Die Beispielimplementierung zeigt dies examplarisch anhand der Methoden <code>ejbCreate</code> und <code>setStreet</code>.<br/> Für programmiersprachliche Typen, die nicht direkt in DB-Typen abbildbar sind, muß im Falle der Bean Managed Persistence der Bean-Entwickler selbst Sorge für die adäquate Abbildung tragen. Das Beispiel illustriert dies anhand des Java-Datumstyps <a fixedType="JDK14" offset="java/util/GregorianCalendar.html" keyword="yes">GregorianCalendar</a>, der manuell in die durch das DBMS erwartete <a href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html">ISO 8601</a>-konforme Darstellung zu überführen ist.</p>
         <p>Einige der möglichen Interaktionen mit der Bean zeigt der Code des Clients aus Beispiel <scriptRef type="example" name="EEJBClient"/>:</p>
         <scriptElement type="example" name="EEJBClient" title="Client der auf eine Entity Bean zugreift" filename="CallPersonBean.java">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/CallPersonBean.java"/>
         </scriptElement>
         <p>Der Client ermittelt zunächst per JNDI eine Referenz auf die Bean, welche unter dem Namen <em>personBean</em> im Verzeichnisdienst registriert ist.<br/> Die erhaltene generische Referenz wird durch Aufruf der statischen Methode <a fixedType="JDK14" offset="javax/rmi/PortableRemoteObject.html#narrow(java.lang.Object, java.lang.Class)" keyword="yes">narrow</a> der Klasse <a fixedType="JDK14" offset="javax/rmi/PortableRemoteObject.html" keyword="yes">PortableRemoteObject</a> typsicher in eine Ausprägung der Home-Schnittstelle (<code>PersonHome</code>) konvertiert.<br/> Der Aufruf der in dieser Schnittstelle durch den Anwender definierten <code>create</code>-Methode sorgt für die serverseitige Instanziierung der EJB, die als Ausprägung der Remote-Schnittstelle geliefert wird. Tatsächlich wird nicht das EJB-Objekt selbst durch den Methodenaufruf retourniert, sondern lediglich ein netzwerktransparenter Verweis darauf, der jedoch clientseitig einer lokalen Objektreferenz gleichgestellt verwendet werden kann.<br/> Ferner wird serverseitig zur Kommunikation mit der EJB ein Home-Objekt erzeugt, welchem eine Stellvertreterrolle für den anfragenden Client zukommt.<br/> Der Aufruf der durch die EJB zur Verfügung gestellten Methode erfolgt identisch zu dem einer Lokalen.</p>
         <p>So dient der Aufruf der Methode <code>create</code> zur Erzeugung von serverseitig instanziiert und transparent persistierten EJB-Objekten sowie den lokalen Java-(Stellvertreter-)Objekten für den Zugriff darauf.<br/> Der Aufruf von <code>getAge</code> zeigt die Nutzung einer in der Remote-Schnittstelle veröffentlichten Zugriffsmethode. Mit <code>getPrimaryKey</code> wird die, in der durch die Remote-Schnittstelle erweiterten Schnittstelle <code>EJBObject</code> angesiedelte, Operation zur Ermittlung des Primärschlüsselwertes eines EJB-Objektes aufgerufen.<br/> Die Methode <code>remove</code> stellt dagegen eine durch die Home-Schnittstelle definierte Operation dar. Durch den Aufruf dieser Methode auf dem durch <code>p1</code> referenzierten Objekt wird durch Ausführung der Beanmethode <code>ejbRemove</code> die die Bean serverseitig repräsentierenden Datenbankeinträge entfernt sowie der durch die Bean belegte Speicherbereich als frei markiert. Alle Versuche nach Aufruf dieser Methode auf der clientseitigen hauptspeicherrepräsentation Wertänderungen durchzuführen führen daher zu einem Fehler.<br/> Die Ermittlung von Referenzen auf existierende EJB-Objekte erfolgt durch die in der Remote-Schnittstelle definierte Methode <code>findByPrimaryKey</code>. Der EJB-Container stellt sicher, daß verschiedene Referenzen auf dasselbe EJB-Objekt synchronisiert in die Datenbank abgebildet werden, so daß keine Inkonsistenzen entstehen.</p>
         <p>Für den Betrieb einer Enterprise Java Bean ist neben den bisher betrachteten Schnittstellen-Komponenten und der Realisierung der Bean selbst auch ein als <em>Deployment Deskriptor</em> bezeichnetes XML-Konfigurationsfile notwendig, welches verschiedene Einstellungsdaten sowie die Schnittstellendaten enthält.<br/> Beispiel <scriptRef type="example" name="EJBDD"/> zeigt ein Beispiel hierfür:</p>
         <scriptElement type="example" name="EJBDD" title="Deployment Deskriptor der Entity Bean" filename="PersonBean-DD.xml">
            <importText URI="../development/vorlesung/sharedScriptParts/EJBExamples/PersonBean-DD.xml"/>
         </scriptElement>
      </span>
      <subtopic name="jdo">1.3 Java Data Objects</subtopic>
      <span xml:base="file:/I:/development/vorlesung/sharedScriptParts/JDO.xml">
         <subsubtopic name="JDOGrundidee">Grundidee</subsubtopic>
         <p>Hintergrund des Ansatzes der <em>Java Data Objects</em> (JDO) ist es, die bestehenden
        Schnittstellenmechanismen dahingehend weiterzuentwickeln, daß die Persistenz von Objekten und Objektgraphen
        für den Programmierer vollständig transparent durch Komponenten der Laufzeitumgebung zur Verfügung gestellt
        werden.<br/>
        Gleichzeitig etabliert JDO eine Abstraktion der verschiedenen Speicherungsmöglichkeiten und erlaubt es
        beispielsweise die dateibasierte Ablage innerhalb des Programmes identisch zur Objektspeicherung
        in einem Datenbankmanagementsystem zu handhaben. Auf dieser Basis läßt sich im Bedarfsfalle den
        Persistenzdienstleister auszutauschen ohne Änderungen am Programmcode zu erfordern.<br/>
        Plakativ wird der Ansatz daher, in Anlehnung an die Zielsetzung der Programmiersprache Java des
        <em>write once -- run anywhere</em>, als <em>write once -- store anywhere</em> charakterisiert.
        </p>
         <subsubtopic name="JDOTechnik">Technik</subsubtopic>
         <p>Um die weitestgehend transparente Handhabung der Objektpersistenz zu gewährleisten bedient sich JDO eines
        Ansatzes der über das alleinige Angebot einer Programmierschnittstelle hinausreicht. Die Zielsetzung
        der möglichst einfach handzuhabenden Interaktion mit den generischen Persistenzmechanismen läßt sich zwar
        durch das Angebot von durch den Programmierer zu implementierenden Schnittstellen und Persistenzklassen
        erreichen, jedoch ist der Einsatz signifikant komplexer als der bestehenden Persistenzschnittstellen.
        Darüberhinaus konterkariert der Zwang bei der Programmerstellung vorgegebene Schnittstellen zu
        berücksichtigen die Zielsetzung weitestgehender Transparenz der angebotenen Speichermechanismen.</p>
         <p>Daher führt JDO die Technik der sog. <em>Bytecodeanreicherung</em> (engl. <em>bytecode enhancing</em>) ein.
        Hierbei wird durch eine Programmkomponente vorübersetzer Bytecode so abgeändert, daß die notwendigen
        Persistenzanweisungen in den bereits erzeugten ausführbaren Bytecode eingewoben werden.<br/>
        Die benötigte Übersetzerkomponente wird durch die jeweilige JDO-Implementierung zur Verfügung gestellt und
        muß durch den Programmierer im Bedarfsfalle lediglich geeignet parametrisiert werden.</p>
         <p>Im Falle der Referenzimplementierung müssen daher alle Klassen, die Objekte ausprägen, welche
        persistiert werden sollen, mit dem Werkzeug entsprechend nachbearbeitet werden. Der notwendige Aufruf
        hat folgende Struktur:
        <code>java com.sun.jdori.enhancer.Main -d enhanced de/jeckle/jdotest/Employee.class de/jeckle/jdotest/Employee.jdo</code>.<br/>
        Dieser Aufruf reichert die bereits übersetzte Klasse <code>Emplyoee</code> innerhalb der Pakethierarchie
        <code>de.jeckle.jdotest</code> um Persistenzdaten an und legt das Ergebnis innerhalb des
        Dateisystemkatalogs <code>de/jeckle/jdotest</code> ab. Zur Anreicherung wird die Konfigurationsdatei
        <code>Employee.jdo</code> herangezogen, die im selben Pfad abgelegt ist wie die Quellcodedatei.</p>
         <p>Alternativ zu diesem Ansatz steht auch die Möglichkeit zur Verfügung die benötigten Anweisungen bereits
        im Quellcode vorzusehen um so dasselbe Resultat zu erzielen, welches durch den Anreicherungsprozeß
        erzeugt wird. Diese Vorgehensweise hat jedoch wegen der damit verbundenen Aufwände kaum praktische Bedeutung
        erlangt und wird daher im folgenden nicht vertieft betrachtet.</p>
         <p>Die Beispiele dieses Kapitels basieren auf der kostenfrei verfübaren JDO-Referenzimplementierung von SUN.
        Diese beschränkt zwar die unterstützten Persistenzmechanismen auf ausschließlich dateibasierte Speicherung und
        sieht keine Ablage in Datenbankmanagmenetsystemen vor.<br/>
        Konzeptionell und programmierseitig ist die Interaktion mit dieser Implementierung jedoch identisch zu
        kommerziell verfügbaren Lösungen und können daher ohne weiteres auf diese und damit beliebige
        Persistenzdienstleister übertragen werden.</p>
         <subsubtopic name="JDOKonfiguration">Konfiguration des Persistenzdienstleisters</subsubtopic>
         <p>Die Abbildung der in der Programmiersprache formulierten Interaktionen auf den konkreten physischen
        Persistenzdienstleister erfolgt sinnvollerweise an einer für alle JDO-nutzenden Applikationen
        zugänglichen Stelle im Rahmen einer Property-Datei.<br/>
        Die Inhalte dieser Datei unterscheiden naturgemäß bei den verschiedenen JDO-Herstellen und inhärent
        mit dem gewählten Persistenztyp. So benötigt die dateibasierte Objektablage offenkundig andere
        Festlegungen als der Zugriff auf ein relationales Datenbankmanagementsystem.<br/>
        Beispiel <scriptRef type="example" name="JDOConfig"/> zeigt die notwendigen Einstellung
        zur Konfiguration der dateibasierten Speicherung mit der SUN-Referenzimplementierung. Dort wird
        mit der <code>PersistenceManagerFactoryClass</code> diejenige Klasse innerhalb des JDO-Rahmenwerkes
        benannt, welche dem Programmierer die Persistenzdienste zur Verfügung stellt. <code>ConnectionURL</code>
        bildet das Bindeglied der Abbildung auf die physische Datei und benennt daher den Speicherort aller
        persistierten Objekte. Die zusätzlichen Angaben dienen der Authentisierung und Zugriffssteuerung beim Zugriff
        auf die erstellte Datei.</p>
         <scriptElement type="example" name="JDOConfig" title="Konfiguration einer JDO-Implementierung" filename="jdo.properties">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/jdo.properties"/>
         </scriptElement>
         <subsubtopic name="JDOStruktur">Struktur der JDO-API</subsubtopic>
         <p>Die JDO-API ist im Rahmen des Java Community Prozesses als Java-Schnittstellensammlung nebst zugehöriger
        Semantikdefinition spezifiziert. Die Implementierung der Schnittstellen erfolgt durch den Anbieter
        der jeweiligen JDO-Implementierung und erfolgt auf den jeweiligen Persistenztyp abgestimmt.<br/>
            <illustrationLink ref="JDOStruct"/> zeigt die grundlegenden Schnittstellen der JDO-API
        sowie die sie anbietenden Klassen der Referenzimplementierung.</p>
         <illustration id="JDOStruct" gfx="dba/jdoStruct.gif" caption="Grundlegende Struktur der JDO-API" width="650"/>
         <p>Die Schnittstelle <code>PersistenceCapable</code> bildet das Rückgrat der gesamten Persistenzbemühungen.
        Jede Klasse, deren Speicherung durch JDO verwaltet werden soll (in Beispiel die Klasse <code>Employee</code>)
        muß diese Schnittstelle zwingend implementieren.<br/>
        Typischerweise erfolgt diese Implementierung jedoch nicht direkt durch den Applikationsprogrammierer, sondern
        wird im Rahmen der Bytecodeanreicherung nachträglich hinzugefügt.<br/>
        Zur Interaktion mit Klassen, deren Implementierung der in <code>PersistenceCapable</code> deklarierten
        Methoden erst nach dem initialen Übersetzungsvorgang hinzugefügt werden kann der JDO-Anbieter die
        Hilfsklasse <code>JDOHelper</code> anbieten. Diese definiert verschiedene, ausschließlich als statisch deklarierte,
        Methoden um mit Objekten von Klassen zu operieren, als würden diese die Schnittstelle
        <code>PersistenceCapable</code> umsetzen, ohne deren Klassen zur tatsächlichen Schnittstellenimplementierung
        verpflichten.<br/>
        Damit stellt <code>JDOHelper</code> die unabdingbare Voraussetzung zur Anwendungsentwicklung
        unter Verwendung der Bytecodeanreicherung dar, da diese erst nach dem Übersetzungsvorgang
        Implementierungen derjenigen Schnittstellen hinzufügt, die bereits im Code verwendeten wurden.
        Ferner bietet die Klasse die Möglichkeit den aktuellen Persistenzzustand eines
        JDO-verwalteten Objektes auszulesen.</p>
         <p>Zur Erzeugung von Objekten, die später den Zugriff auf das physische Speichermedium
        regeln dienen die Umsetzungen der Schnittstelle <code>PersistenceManagerFactory</code>. Sie erlaubt die
        Parametrisierung und Verwaltung der Verbindung zum Persistenzmedium. Bereitgestellt wird die
        Implementierung, im Falle der Referenzimplementierung, durch die Klasse
        <code>com.sun.jdori.fostore.FOStorePMF</code>.<br/>
        Die Verbindung zwischen Schnittstelle und tatsächlicher Implementierung wird im Rahmen der
        in Beispiel <scriptRef type="example" name="JDOConfig"/> gezeigten JDO-Konfiguration definiert. Zum Wechsel
        des Persistenzanbieters -- etwa von der durch die Referenzimplementierung angebotenen dateibasierten
        Speicherung auf eine datenbankgestützte Umsetzung -- genügt im die Abänderung dieses Eintrages in der
        Konfigurationsdatei.</p>
         <p>Klassen, welche die Schnittstelle <code>PersistenceManagerFactory</code> implementieren, werden
        zur Erzeugung von sog. <code>PersistenceManger</code>n herangezogen. Umsetzungen dieser Schnittstelle
        (im Falle der Referenzimplementierung ist dies die Klasse
        <code>com.sun.jdori.common.PersistenceManagerWrapper</code>) dienen zur Interaktion mit der Persistenzveraltung
        innerhalb der JDO nutzenden Applikation. Alle Änderungen des Zustandes eines persistenten Objektes
        werden durch diese Klasse abgewickelt.</p>
         <p>JDO wickelt sämtliche Zugriffe auf die persistenten Daten transaktionsgesichert ab. Dieser Mechanismus
        wird auf der abstrakten Ebene der API durch die Schnittstelle <code>Transaction</code> definiert und steht
        daher für alle Persistenzanbieter gleichermaßen zur Verfügung.<br/>
        Die Schnittstelle definiert alle zur Transaktionssteuerung benötigten Operationen (darunter <code>begin</code>,
        <code>commit</code> und <code>rollback</code>) an.<br/>
        Im Falle der Referenzimplementierung wird die Schnittstelle durch die Klasse
        <code>com.sun.jdori.common.query.QueryImpl</code> umgesetzt.</p>
         <p>Zusätzlich sieht JDO eine abstrakte Möglichkeit zur Formulierung von Anfragen auf den verwalteten
        Datenbestand vor. Die notwendige Schnittstelle wird durch <code>Query</code> bereitgestellt.<br/>
        Hierfür müssen die verschiedenen JDO-Implementierungen ebenfalls eigene Umsetzungen vorsehen.</p>
         <subsubtopic name="JDOCreateStore">Erzeugen eines persistenten Objektspeichers</subsubtopic>
         <p>Zur Erzeugung eines Objektspeichers ist bereits die Nutzung der Implementierungen der
        zentralen JDO-Schnittstellen sowie die der Transaktionssteuerung notwendig.<br/>
        Das Beispiel zeigt die notwendigen Schritte zur Erzeugung eines persistenten Objektspeichers.<br/>
        Zunächst lädt das Beispiel die Konfiguration aus der Eigenschaftsdatei des Beispiels <scriptRef type="example" name="JDOConfig"/>. Anschließend wird durch die mit <code>true</code> belegte
        implementierungsspezifische Eigenschaft <code>com.sun.jdori.option.ConnectionCreate</code>
        festgelegt, daß im Rahmen des Verbindungsaufbaus auch notwendigenfalls der Objektspeicher neu erzeugt wird.<br/>
        Die Interaktion mit JDO beginnt durch die Erzeugung eines <code>PersistenceManagerFactory</code> konformen
        Objektes durch den Aufruf <code>getPersistenceManagerFactory</code> unter Auswertung der zuvor geladenen und
        ergänzten Konfigurationseigenschaften.<br/>
        Nach der Erzeugung des Factory-Objektes kann mittels diesem durch den Aufruf
        <code>getPersistenceManager</code> ein Objekt erzeugt werden, das die
        Interaktion mit dem Objektspeicher bereitstellt. Durch die Ermittlung des Persistenzmanagers
        wird gleichzeitig eine Verbindung zum Persistenzanbieter aufgebaut.<br/>
        Ausgehend von diesem Verwaltungsobjekt kann durch Definition einer <gerquot>leeren</gerquot> Transaktion --
        d.h. einer Transaktion, die jenseits der Erzeugung des transaktionalen Kontexts und seines Abschlusses
        mit <em>committ</em>, keine Operationen definiert -- der Objektspeicher erzeugt werden.<br/>
        Den Abschluß der Interaktion mit dem Objektspeicher bildet die Beendigung der Verbindung durch
        Ausführung der Methode <code>close</code> des Verbindungsobjektes.</p>
         <scriptElement type="example" name="JDOCreate" title="Erzeugung eines persistenten Objektspeichers" filename="JDOCreateDB.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDOCreateDB.java"/>
         </scriptElement>
         <subsubtopic name="JDOPara">Parametrisierung der Persistenz</subsubtopic>
         <p>Grundsätzlich können Ausprägungen jeder beliebigen Javaklasse durch JDO persistiert werden, solange diese
        Klassen die Schnittstelle <code>PersistentCapable</code> explizit im Quellcode implementieren oder die
        benötigte Implementierung im Rahmen der Bytecodeanreicherung hinzugefügt wird.<br/>
        Zur Steuerung des konkreten Persistenzverhaltens wird eine zusätzliche Konfigurationsdatei benötigt.
        Diese bedient sich der bekannten XML-Sytnax und definiert das Persistenzverhalten der durch JDO
        zu verwaltenden Klasseninstanzen näher. <br/>
        Beispiel <scriptRef type="example" name="Employee.java"/> zeigt zunächst die zu persistierende
        Klasse <code>Employee</code>.</p>
         <scriptElement type="example" name="Employee.java" title="Zu persistierende Javaklasse" filename="Employee.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/Employee.java"/>
         </scriptElement>
         <p>Die Nutzung JDO-gestützter Objektpersistenz impliziert keinerlei Modifikationen
        oder Ergänzungen am Quellcode. Ebenso sind keinerlei Umsetzungskonventionen einzuhalten, die
        im Beispiel definierten <code>get</code>- und <code>set</code>-Methoden dienen lediglich der vereinfachten
        Interaktion.</p>
         <p>Das Beispiel <scriptRef type="example" name="Employee.jdo"/> illustriert eine
        Parameterdatei zur Definition des spezifischen Persistenzverhaltens von Objekten der Klasse
        <code>Employee</code>.</p>
         <scriptElement type="example" name="Employee.jdo" title="Parametrisierung der Objektpersistenz" filename="Employee.jdo">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/Employee.jdo"/>
         </scriptElement>
         <p>Die XML-Datei definiert zunächst den Paket- und Klassennamen der zu persistierenden Klasse mittels des
        Attributs <code>name</code> der XML-Elemente <code>package</code> und <code>class</code>.<br/>
        Innerhalb eines <code>class</code>-Elements kann für jedes Attribut der Javaklasse ein mit
        <code>field</code> benanntes Element zur näheren Charakterisierung des Speicherungsverhaltens angegeben werden.<br/>
        Ein solches Element trägt zunächst im Attribut <code>name</code> den klassenweit eindeutigen Namen
        des Attributs und erlaubt die Festlegung des spezifischen Persistenzverhaltes mittels der Belegung des
        Attributs <code>persistence-modifier</code>. Ist dieses mit dem Wert <code>persistent</code> versehen, so
        wird ein so gekennzeichnetes Attribut durch JDO im Datenspeicher persistiert. Trägt das XML-Attribut den
        Wert <code>none</code>, so wird das Javaattribut bei der Abbildung in den JDO-Datenspeicher ignoriert.<br/>
        Zusätzlich besteht die Möglichkeit durch die Belegung mit <code>transactional</code> die Zwischenspeicherung
        des Attributwertes während der Abarbeitung einer Transaktion zu erzwingen, um so eine spätere Wiederherstellung
        (nach einem Aufruf von <code>rollback</code>) zu gewährleisten. Jedoch werden Felder, die so gekennzeichnet sind,
        nicht persistent in den Datenspeicher übernommen, sondern stehen nur während der Programmlaufzeit zur
        Verfügung.<br/>
        Fehlt diese Spezifikation zu einem Attribut in der XML-Datei, so wird vorgabegemäß die Belegung mit
        <code>persistent</code> angenommen, sofern es in der beherbergenden Javaklasse nicht als <code>static</code>,
        <code>transient</code> oder <code>final</code> ausgewiesen ist.</p>
         <p>Attribute vom Typ einer Sammlungsklasse, wie sie durch die
        <a href="http://www.jeckle.de/vorlesung/java/script.html#collectionAPI">
               <em>Collection API</em>
            </a>
        definiert werden müssen
        zusätzlich mit einem <code>collection</code>-Element, welches innerhalb des <code>field</code>-Elements
        plaziert ist, charakterisiert. Das <code>collection</code>-Element spezifiziert durch sein
        Attribut <code>element-type</code> den Typ der Elemente in der Sammlung festlegt. Zusätzlich kann durch
        das Boole'sche-Attribut <code>embedded-element</code> gesteuert werden, ob die Inhalte des Sammlungsobjektes
        zusammen mit dem die Sammlung referenzierenden Objekt persistiert werden sollen.</p>
         <p>Das Beispiel legt für alle Attribute der Klasse <code>Employee</code> ihre persistente Speicherung fest
        (Belegung des XML-Attributs <code>persistence-modifier</code> für alle Attribute <code>persistent</code>);
        ebenso wird die in Objekten des Typs <em>Employee</em>, unter dem Namen <code>projects</code>, enthaltene
        Sammlungsinstanz einschließlich ihrer Inhaltsobjekte des Standard-API-Typs <code>String</code> dauerhaft
        abgespeichert.</p>
         <p>Über diese Festlegungen hinaus gestattet das Parametrisierungsformat die Festlegung spezifischer
        Konsistenzsemantik in Gestalt der Auszeichnung eines <em>Primärschlüssels</em>. Dieses aus dem relationalen
        Modell bekannte Konstrukt fordert die Eindeutigkeit eines Attributs oder einer Kombination von Attributen
        über die gesamte Menge der Ausprägungen eines Typs.<br/>
        Durch die Unterstützung als abstraktes JDO-Konstrukt steht dieses Konzept zur Konsistenzsicherung auch
        für Applikationen zur Verfügung, die sich nicht relationaler Datenbanken als Persistenzdienstleister
        bedienen.<br/>
        Zur Realisierung des Primärschlüsselkonzeptes ist das als Schlüssel zu interpretierende Attribut
        in der XML-Beschreibung zusätzlich mit dem XML-Attribut <code>primary-key</code> zu versehen, welches
        den Wert <code>true</code> tragen muß. Zusätzlich ist innerhalb des Elements <code>class</code> diejenige
        Klasse anzugeben, welche das Attribut beherbergt, das als Schlüssel herangezogen werden soll.<br/>
            <scriptRef type="example" name="EmployeePK.jdo"/> zeigt die notwendigen Modifikationen an der
        Parameterdatei des Beispiels <scriptRef type="example" name="Employee.jdo"/> um das Java-Attribut
        <code>name</code> als Primärschlüssel festzulegen. Die primärschlüsselanbietende Klasse ist in diesem
        Falle die Klasse <code>Employee</code> selbst, weshalb sich ihr Name auch im XML-Attribut
        <code>objectid-class</code> des <code>class</code>-Elements findet.</p>
         <scriptElement type="example" name="EmployeePK.jdo" title="Parametrisierung der Objektpersistenz und Definition eines Primärschlüssels" filename="EmployeePK.jdo">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/EmployeePK.jdo"/>
         </scriptElement>
         <p>Konsequenz der Einführung eines Primärschlüsselattributs ist die Überwachung der damit einhergehenden
        Konsistenzbedingungen durch das JDO-Laufzeitsystem. So führen Versuche zwei Objekte, die sich in der
        Belegung des als Primärschlüssel definierten Attributs nicht unterscheiden ebenso zu Fehlern wie schreibende
        Zugriffe auf dergestalt ausgezeichnete Attribute.</p>
         <subsubtopic name="JDOByteCodeEnh">Anreicherung des Bytecodes</subsubtopic>
         <p>Voraussetzung der Persistenzverwaltung eines Objektes durch JDO ist die entsprechende Modifikation
        dieses Objektes, konkret die Implementierung der in <code>PersistenceCapable</code> festgelegten
        Operationen durch Methoden der objekterzeugenden Klasse.<br/>
        Dies wird jedoch nur in Ausnahmefällen durch den Applikationsprogrammierer direkt vorgenommen. Häufigste
        Eionsatzform der JDO-API ist die Anwendung der Bytecodeanreicherung, welche die Implementierung der notwendigen
        Funktionalität automatisiert vornimmt und diese nach dem eigentlichen Übersetzungsvorgang in den erstellten
        Bytecode einbringt.<br/>
            <illustrationLink ref="JDOBCE"/> zeigt die daher notwendigen zwei Übersetzungsschritte.</p>
         <illustration id="JDOBCE" gfx="dba/jdoBCE.gif" caption="Erzeugung und Anreicherung des Bytecodes" width="650"/>
         <p>Die Illustration versammelt die zur Erzeugung und Anreicherung des Bytecodes der per JDO zu persistierenden
        Klasse <code>Employee</code> aus Beispiel <scriptRef type="example" name="Employee.java"/>. Zur Anreicherung des
        Bytecodes werden die in Beispiel <scriptRef type="example" name="Employee.jdo"/> getroffenen Parametrisierungen
        herangezogen.<br/>
        Zunächst wird der im Paket <code>de.jeckle.jdotest</code> abgelegte Quellcode <code>Employee.java</code>
        mit dem Javacompiler in (gewöhnlichen) Bytecode übersetzt.<br/>
        Anschließend wird dieser vermöge des in der JDO-Referenzimplementierung vorhandenen Werkzeuges
        <code>Enhancer</code> um die Implementierung der in der Schnittstelle <code>PersistenceCapable</code>
        definierten Operationen angereichert. Hierzu wird dem Enhancer (bereitgestellt durch die Klasse
        <code>com.sun.jdori.enhancer.Main</code> zunächst das Zielverzeichnis des zu erzeugenden
        Bytecodes mittels des Parameters <code>d</code> übergeben. Naheliegernderweise kann der aus dem
        ursprünglichen Bytecode durch Erweiterung erzeugte nicht die Ausgangsdatei überschreiben, daher
        wird der angereicherte Bytecode im Verzeichnis <code>enhanced</code> gespeichert. Zusätzlich
        ist dem Enhancer der vollqualifizierte Name der anzureichernden Klasse sowie der vollqualifizierte
        Pfad der Parameterdatei (im Beispiel: <code>de/jeckle/jdotest/Employee.jdo</code>) zu übergeben.
        Diese muß im Falle des Einsatzes der Referenzimplementierung zwingend die Extension <code>jdo</code> besitzen.
        </p>
         <subsubtopic name="JDOStates">Status JDO-verwalteter Objekte</subsubtopic>
         <p>Im Zusammenspiel zwischen transienter Objektverwaltung durch die Applikation im Hauptspeicher
        und persistenter Objektverwaltung durch JDO im Hintergrundspeicher werden verschiedene Status eines
        verwalteten Objekts unterschieden zwischen denen explizite Übergänge durch API-Aufrufe vorgegeben sind bzw.
        implizit durch Operationen auf den involvierten Objekten bestehen.<br/>
        Im Detail werden folgende Status unterschieden:</p>
         <ul>
            <li>
               <b>Transient</b>: Instantiierte Objekte im Hauptspeicher. Hierunter fallen alle noch nicht innerhalb
            von Transaktionen persistierten Objekte ebenso wie unangereicherte Javaobjekte und solche die ausschließlich
            über Attribut verfügen, die als in der XML-Parametrisierungsdatei als
            <code>transient</code> gekennzeichnet sind.</li>
            <li>
               <b>Persistent (neu)</b>: Objekte, die innerhalb einer laufenden (d.h. weder durch
            <code>commit</code> noch <code>rollback</code> abgeschlossenen) Transaktion erzeugt wurden.<br/>
            Endet eine Transaktion, etwa durch Programmabbruch, in diesem Zustand, so werden die Objekte
            mit diesem Status nicht dauerhaft gespeichert.</li>
            <li>
               <b>Persistent (gelöscht)</b>: Objekte, die in einer noch nicht abgeschossenen Transaktion
            persistiert und anschließend gelöscht wurden.<br/>
            Endet eine Transaktion, etwa durch Programmabbruch, in diesem Zustand, so werden die Objekte
            mit diesem Status nicht dauerhaft gespeichert, da sowohl der Persistierungs- als auch der
            anschließende Löschvorgang noch nicht durch <code>commit</code> bestätigt wurden.</li>
            <li>
               <b>Dauerhaft persistiert und ungelesen (hollow)</b>: Objekte, die durch Abschluß einer Transaktion
            mit <code>commit</code> dauerhaft gespeichert wurden und auf die noch kein Zugriff (weder lesend
            noch schreibend) erfolgte.</li>
            <li>
               <b>Persistent und gelesen (clean)</b>: Objekte, die persistent im Hintergrundspeicher abgelegt
            wurden und auf die bisher lediglich lesende Zugriffe erfolgten.</li>
            <li>
               <b>Persistent verändert und unsynchronisiert (dirty)</b>: Persistentes Objekt, dessen Inhalt
            im Rahmen einer noch nicht abgeschlossenen Transaktion verändert wurde.<br/>
            Wurden zwar Attributinhalte eines persistenten Objektes verändert, jedoch keine Wertänderungen
            vorgenommen, d.h. in ein Attribut wird mit demselben Wert belegt, den es bereits enthält, dann
            steht es dem JDO-Implementierer frei diese Schreiboperation so zu implementieren, daß nicht der
            Zustand <em>dirty</em> eingenommen wird.<br/>
            Zusätzlich kann jedes Objekt durch Aufruf der API-Methode <code>makeDirty</code> manuell in diesen
            Zustand versetzt werden.<br/>
            Als Folge der Schreiboperation im Hauptspeicher differieren dessen Inhalte von denen des
            persistenten Objektspeichers.<br/>
            Durch Aufruf der API-Methode <code>refresh</code> werden die Inhalte von Haupt- und Hintergrundspeicher
            synchronsiert, d.h. Inhalte des Hintergrundspeichers werden in den Hauptpeicher übernommen.</li>
            <li>
               <b>Persistent gelöscht und unsynchronisiert (deleted)</b>: Persistentes Objekt, das im
            Rahmen einer noch nicht abgeschlossenen Transaktion gelöscht wurde.<br/>
            Als Folge der Löschoperation im Hauptspeicher differieren dessen Inhalte von denen des
            persistenten Objektspeichers und alle Leseoperationen auf nicht-Primärschlüsselfelder führen
            zu Laufzeitfehlern.</li>
         </ul>
         <p>
            <illustrationLink ref="JDOStatus"/> zeigt die verschiedenen JDO-Status sowie die Ereignisse, die
        zu Zustandsübergängen führen, in der Übersicht.</p>
         <illustration id="JDOStatus" gfx="dba/jdoStatus.gif" caption="Mögliche Status JDO-verwalteter Objekte" width="650"/>
         <subsubtopic name="JDOStore">Speicherung von Objekten</subsubtopic>
         <p>Zur Speicherung von Objekten, deren Klassen durch den Bytecodeanreicherungsprozeß nachbearbeitet wurden,
        bietet die JDO-API die Aufrufe <code>makePersistent</code> und <code>makePersistentAll</code> an. Diese
        werden innerhalb eines Transaktionskontextes als Methoden eines <code>PersistenceManager</code>-Objekte
        ausgeführt.<br/>
        Beispiel <scriptRef type="example" name="JDOStoreObj"/> zeigt die Speicherung von drei Objekten der
        Klasse <code>Emplyoee</code>, deren übersetzter Bytecode durch Anreicherung zur JDO-Kompatibilität
        modifiziert wurde.<br/>
        Zunächst wird mit <code>empCol</code> vom Standardtyp <code>Vector</code> eine Sammlungsobjekt zur
        Aufnahme von Objektreferenzen definiert. Dieser Objektsammlung werden die Referenzen auf die erzeugten
        <code>Emplyoee</code>-Objekte (<code>emp1</code>, <code>emp2</code> und <code>emp3</code>) hinzugefügt.<br/>
        Als Voraussetzung der Interaktion mit dem Objektspeicher muß zunächst eine Transaktion eröffnet werden.
        Hierzu muß zunächst durch Aufruf der Methode <code>currentTransaction</code> die der
        <code>PersistenceManager</code>-Instanz zugeordnete Transaktion ermittelt werden. Ausgehend vom
        gelieferten Ergebnisobjekt kann durch Ausführung der Methode <code>begin</code> eine neuer
        Transaktionskontext eröffnet werden.<br/>
        Der Aufruf von <code>makePersistentAll</code> persistiert bei Übergabe der Objektsammlung alle in der
        Sammlung referenzierten Objekte. Alternativ können Einzelobjekte durch die Methode <code>makePersistent</code>
        in den Zustand dauerhafter Speicherung überführt werden.<br/>
        Zur Übernahme in den Hintergrundspeicher muß der Transaktionskontext durch Aufruf von <code>commit</code>
        abgeschlossen werden. Der Aufruf von <code>rollback</code> würde stattdessen alle in der Transaktion
        vorgenommenen Änderungen verwerfen und auf den im Hintergrundspeicher verwalteten Datenzustand zurückgesetzt.</p>
         <scriptElement type="example" name="JDOStoreObj" title="Speicherung von Objekten mit JDO" filename="JDOStoreObj.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDOStoreObj.java"/>
         </scriptElement>
         <p>Würde wie im Beispiel <scriptRef type="example" name="EmployeePK.jdo"/> gezeigt das Attribut <code>name</code>
        der Klasse <code>Employee</code> als Primärschlüssel definiert sein, so würde der Persistierungsversuch
        des durch <code>emp3</code> referenzierten Objektes einen Laufzeitfehler liefern, da mit <code>emp2</code>
        bereits ein Objekt mit derselben Belegung des Attributs <code>name</code> persistiert wurde.</p>
         <subtopic name="JDORollback">Rücksetzen von Transaktionen</subtopic>
         <p>Treten während der Interaktion mit dem Persistenzspeicher, d.h. während eines noch nicht mit
        <code>commit</code> abgeschlossenen Transaktionskontextes Fehler auf, so können durch Aufruf
        der Methode <code>rollback</code> alle im aktuellen Kontext vorgenommen Änderungen auf den Stand
        vor Beginn der Transaktion zurückgesetzt werden.<br/>
        Beispiel <scriptRef type="example" name="JDORollback"/> zeigt das Verhalten der Methode
        <code>rollback</code> am Beispiel. Durch die Schreiboperation innerhalb der geöffneten Transaktion
        wird der Wert des Attributs <code>name</code> zwar verändert, jedoch durch Aufruf von <code>rollback</code>
        wieder auf den ursprünglichen Wert zurückgesetzt.</p>
         <scriptElement type="example" name="JDORollback" title="Transaktionen mit JDO" filename="JDORollback.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDORollback.java"/>
         </scriptElement>
         <p>Die Ausführung des Beispiels liefert folgende Ausgabe:<br/>
            <code>
               <pre>Employee named Marta Mayer works in department null
works in projects:
Martha gets married and changes her name
Employee named Marta Smith works in department null
works in projects:
Suppose and error happens now ...
Rolling back
Employee named Marta Mayer works in department null
works in projects:</pre>
            </code>
         </p>
         <subtopic name="JDONonTransact">Schreiboperationen ohne Transaktionsschutz</subtopic>
         <p>Ist in bestimmten Anwendungsfällen die Arbeit ohne Transaktionsschutz -- und damit ohne
        die Möglichkeit der expliziten Rücksetzung von Änderungen mittels <code>rollback</code> oder der
        impliziten Rücksetzung nach einem Systemausfall -- gewünscht, so kann dies durch Aktivierung der
        Schreibfunktionalität ohne Transaktionsschutz erreicht werden.<br/>
        Hierzu muß de Methode <code>setNontransactionalWrite</code> mit dem Übergabeparameter <code>true</code>
        für eine Transaktion aufgerufen werden.<br/>
        Das nachfolgende Beispiel zeigt als Modifikation von Beispiel <scriptRef type="example" name="JDOStoreObj"/>
        die persistente Übernahme einer Wertänderung ohne Transaktionsschutz.</p>
         <scriptElement type="example" name="JDONonTW" title="Schreiboperation ohne Transaktionsschutz" filename="JDONonTransact.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDONonTransact.java"/>
         </scriptElement>
         <subtopic name="JDOList">Traversierung des persistenten Objektbestandes</subtopic>
         <p>Zugriffe auf alle im Hintergrundspeicher verwalteten Objekte werden ebenfalls einheitlich durch
        Methoden der Implementierung der Schnittstelle <code>PersistenceManager</code> abgewickelt. Zur
        Traversierung des vollständigen Bestandes aller Instanzen einer Klasse bietet diese Schnittstelle
        die Operation <code>getExtent</code> an. Sie liefert alle Elemente der Extension (d.h. der Gesamtheit
        von Ausprägungen) einer gegebenen Klasse.<br/>
        Beispiel <scriptRef type="example" name="JDOList.java"/> zeigt die Verwendung der Methode. Als Parameter
        wird diejenige Klasse übergeben, deren Ausprägungen zu ermitteln sind. Zusätzlich kann durch einen
        <name>Boole</name>'schen Schalter gesteuert werden, ob auch Subklassen der übergebenen Klasse retourniert werden sollen.<br/>
        Der Aufruf liefert eine Sammlung von Objekten des Typs, welcher der Methode <code>getExtent</code>
        übergeben wurde.</p>
         <scriptElement type="example" name="JDOList.java" title="Traversierung des Objektbestandes" filename="JDOListObj.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDOListObj.java"/>
         </scriptElement>
         <subtopic name="JDOQuery">Anfragen an den persistenten Objektbestand</subtopic>
         <p>Als mächtige Alternative zur manuellen Traviersierung einer Objektextension spezifiziert JDO
        die Verwendung einer eigenen Anfragesprache auf Basis des Standards der <em>Object Query Language</em> (OQL)
        der Object Database Management Group (ODMG).<br/>
        Diese -- als <em>JDO Object Query Language</em> (JDOQL) bezeichnete -- Anfragesprache ist direkt in die
        JDO-API integriert und wird über verschiedene Einzelmethoden genutzt. Aus diesem Grunde sind JDOQL-Anfragen
        nicht direkt mit den konsizsen SQL- oder OQL-Anfragen vergleichbar.<br/>
        Beispiel <scriptRef type="example" name="JDOQuery.java"/> zeigt die Einbettung der Anfragesprache in die JDO-API.</p>
         <scriptElement type="example" name="JDOQuery.java" title="Anfrage auf den persistenten Objektbestand mittels OQL" filename="JDOQuery.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDOQuery.java"/>
         </scriptElement>
         <p>Das Beispiel illustriert eine Anfrage, die alle <code>Employee</code>-Objekte liefert, deren
        <code>department</code>-Attribut mit dem Wert <code>B042</code> belegt ist und liefert die
        nach dem Inhalt des Attributes <code>name</code> in aufsteigender Reihenfolge sortiert.<br/>
        Hierzu wird zunächst die vollständige Extension der Klasse <code>Employee</code> ermittelt. Allerdings
        Extrahiert dieser Aufruf noch keine Werte aus dem persistenten Objektspeicher, sondern schafft nur
        die Grundlagen einer späteren manuellen Traversierung oder der Anfrage via JDOQL.<br/>
        Zur Vorbereitung der tatsächlichen physischen Anfrage wird zunächst eine Zeichenkette geeignet
        belegt, um als Filterausdruck dienen zu können, der auf die vollständige Extension angewandt wird.
        Im Beispiel ist dieser Filterausdruck mit <code>department == \"B042\"</code> belegt. Aus Gründen
        der Zeichenkettenverarbeitung in Java muß hierzu der notwendige Einschluß des zu suchenden Wertes
        in Anführungszeichen geeignet maskiert werden.<br/>
        Nach diesen Vorbereitungsschritten kann durch den Aufruf der durch das <code>PersistenceManager</code>-kompatible
        Objekt bereitgestellten Methode <code>newQuery</code> ein neues Anfrageobjekt (vom Typ <code>Query</code>)
        erzeugt werden.<br/>
        Dieses Objekt erlaubt nach der gezeigten Festlegung des Anfrageumfanges die Parametrisierung der Anfrage.
        Das Beispiel illustriert dies am Aufruf der Methode <code>setOrdering</code>, die es erlaubt eine
        bestimmte Sortierreihenfolge der gelieferten Ergebnisse vorzugeben.<br/>
        Zusätzlich kann durch die optionale Ausführung der Methode <code>compile</code> eine Prüfung der zusammengestellten
        Anfrage erfolgen, die zusätzlich auch interne implementierungsspezifische Optimierungen vornehmen kann.<br/>
        Abschließend erfolgt die Ausführung der Anfrage durch Aufruf der Methode <code>execute</code>, welche die
        Anfrageergebnisse konform zur Standardschnittstelle <code>Collection</code>
        zurückliefert.</p>
         <subtopic name="JDODel">Löschen von Objekten</subtopic>
         <p>Zur Entfernung eines Objektes aus dem Objektspeicher stellt die Schnittstelle
        <code>PersistenceManager</code> die Methode <code>deletePersistent</code> zur Verfügung, welche
        ein einzelnes hauptspeicherresidentes Objekt aus dem persistenten Speicher löscht, bzw.
        mit <code>deletePersistentAll</code> eine Möglichkeit alle durch eine Sammlung referenzierten
        Objekte zu entfernen.<br/>
        Da es sich hierbei um einen schreibenden Zugriff handelt, muß dieser in einen Transaktionskontext
        eingebettet werden oder explizit transaktionslos durchgeführt werden wie in Beispiel <scriptRef type="example" name="JDONonTW"/> gezeigt.<br/>
        Beispiel <scriptRef type="example" name="JDODelete"/> zeigt die Löschung unter Verwendung eines
        Transaktionskontextes.</p>
         <scriptElement type="example" name="JDODelete" title="Löschen eines Objektes aus dem persistenten Objektbestand" filename="JDODeleteObj.java">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/JDODeleteObj.java"/>
         </scriptElement>
         <subtopic name="JDOSwitch">Migration zu einem anderen Persistenzdienstleister</subtopic>
         <p>Der JDO-Ansatz tritt mit dem Versprechen auf vollständig sowohl unabhängig vom verwendeten
        Persistenzmedium (etwa: Datenbank, Dateisystem, etc.) als auch der eingesetzten JDO-Implementierung zu sein.
        Diese Zielsetzung wird nachfolgend auf Basis des im vorhergehenden diskutierten <code>Employee</code>-Beispiels
        untersucht. Hierzu wird die frei verfügbare JDO-Implementierung <em>TJDO</em> eingesetzt, welche verschiedene
        Datenbankmanagementsysteme zur Speicherung der Javaobjekte heranziehen kann. Im Beispiel wird das
        DBMS <em>MySQL</em> Persistierung der Applikationsobjekte genutzt.</p>
         <p>Zur Portierung der bestehenden Applikation ist lediglich die Anpassung der JDO-Eigenschaften
        (Property-Datei) vorzunehmen, um den neuen Persistenzdienstleister sowie die verschiedenen DBMS-Spezifika
        zu berücksichtigen.<br/>
        Beispiel <scriptRef type="example" name="tjdoprop"/> zeigt die neuen Inhalte.</p>
         <scriptElement type="example" name="tjdoprop" title="Konfiguration der JDO-Implementierung TJDO" filename="tjdo.properties">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/tjdo.properties"/>
         </scriptElement>
         <p>Zunächst werden die bereits in der Konfiguration der Referenzimplementierung durch Beispiel
        <scriptRef type="example" name="JDOConfig"/> genutzten Eigenschaften zur Identifikation
        derjenigen Klasse, welche die JDO-Schnittstelle <code>PersistenceManagerFactory</code> implementiert sowie
        zur Festlegung der Verbindungs-URL und des zu verwendenden Benutzernamens uns Passwortes an die neuen
        Gegebenheiten adaptiert. Konkret wird die durch TJDO bereitgestellte Klasse
        <code>com.triactive.jdo.PersistenceManagerFactoryImpl</code> als <code>PersistenceManagerFactory</code>
        konforme Implementierung sowie die Identifikation der zu verwendenden Datenbank nebst Benutzername
        und Anmeldekennwort bekanntgegeben.<br/>
        Zusätzlich wird mit <code>com.triactive.jdo.autoCreateTables</code> eine implementierungsspezifische
        Eigenschaft mit <code>true</code> belegt, die TJDO veranlaßt im Bedarfsfalle benötigte Tabellenstrukturen
        automatisiert zu erzeugen.</p>
         <p>Zusätzlich erfordert die verwendete JDO-Implementierung die Adaption der im Rahmen des
        Bytecodeanreicherungsprozesses herangezogenen Konfigurationsdatei (Beispiel <scriptRef type="example" name="Employee.tjdo"/>). Auf diesem Wege wird dem Programmierer
        die Möglichkeit eröffnet die Abbildung auf relationale Tabellenstrukturen beeinflussen.
        In der Konsequenz erfordert der Wechsel der JDO-Implementierung die Wiederholung des
        Anreicherungslaufes für den Bytecode der zu persistierenden Klassen.</p>
         <scriptElement type="example" name="Employee.tjdo" title="Parametrisierung der Objektpersistenz" filename="Employee.tjdo">
            <importText URI="../development/vorlesung/sharedScriptParts/examples/jdo/Employee.tjdo"/>
         </scriptElement>
         <p>Weitere Änderungen an den zu persistierenden Klassen oder den mit deren Objekten operierenden
        Applikationen ist nicht notwendig, alle Zugriffe werden nach den oben beschriebenen Änderungen
        transparent und ohne Neuübersetzung datenbankbasiert abgewickelt.</p>
         <subtopic name="vglJDBCEJBJDO">Vergleich der verschiedenen Persistenzansätze</subtopic>
         <p>Abschließend seien die charakteristischen Eigenschaften der drei diskutierten Persistenzansätze
        JDBC, EJB und JDO kurz vergleichend nebeneinandergestellt.</p>
         <tabular>
            <head length="4">
               <column title="Merkmal"/>
               <column title="JDBC"/>
               <column title="EJB"/>
               <column title="JDO"/>
            </head>
            <body>
               <row>
                  <cell>Transaktionsunterstützung</cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
               </row>
               <row>
                  <cell>Anfragemöglichkeit</cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
               </row>
               <row>
                  <cell>Standardisiertes API</cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
               </row>
               <row>
                  <cell>Standardanfragesprache</cell>
                  <cell>
                     <yes/>
                     <br/>SQL</cell>
                  <cell>
                     <yes/>
                     <br/>SQL/EJBQL</cell>
                  <cell>
                     <yes/>
                     <br/>JDOQL</cell>
               </row>
               <row>
                  <cell>Unterstützte<br/> Hintergrundspeicher</cell>
                  <cell>RDBMS</cell>
                  <cell>RDMBS<br/>
                Integrationsmiddleware</cell>
                  <cell>RDBMS, ORDBMS<br/>Integrationsmiddleware,<br/>Dateisystem,<br/> bel. andere</cell>
               </row>
               <row>
                  <cell>Transparenter Zugriff<br/>
                auf persistierte Daten</cell>
                  <cell>
                     <no/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                  </cell>
               </row>
               <row>
                  <cell>Berücksichtigung existierender <br/>relationaler Strukturen</cell>
                  <cell>
                     <yes/>
                  </cell>
                  <cell>
                     <yes/>
                     <br/>bei bean managed persistence</cell>
                  <cell>
                     <yes/>
                     <br/>allerdings nicht im Standard vorgesehen</cell>
               </row>
            </body>
         </tabular>
         <p>Die Tabelle zeigt klar, daß alle drei Persistenzmechanismen grundlegende Eigenschaften
        teilen, sich jedoch auch in zentralen Charakteristika unterscheiden.<br/>
        Während sowohl JDBC als auch EJBs die direkte Verwendung von SQL-Anfragen gestatten bietet
        JDO mit JDOQL eine eigenständige Anfragesprache, die direkt in die Sprach-API eingebettet ist.
        Für EJBs existiert neben den in Kapitel 1.2 gezeigten Mechanismen auch die Möglichkeit der
        Verwendung der EJB-spezifischen Anfragesprache <em>EJBQL</em>, die jedoch hier nicht betrachtet wurde.<br/>
        Hinsichtlich der jeweils unterstützten Hintergrundspeicherarchitekturen zur Realisierung der Persistenz
        treten jedoch deutliche Unterschiede zu Tage. So ist der Einsatz der JDBC-API auf relationale Datenquellen,
        bzw. Datenquellen die eine relationale Sicht anbieten, beschränkt. Innerhalb der EJB-Architektur können
        hingegen neben den -- hier diskutierten JDBC-basierten Mechanismen -- auch die Dienste einer
        Integrationsmiddleware zu Speicherung herangezogen werden und so eine gewisse Unabhängigkeit vom
        physischen Speichermedium erreicht werden. Einzig JDO bietet durch seine starke Abstraktion
        die Möglichkeit beliebige Persistenzdienstleister zu nutzen.<br/>
        Zur effizienten Abwicklung dieses speicherformunabhängigen Zugriffs etabliert JDO notwendigerweise
        eine stark abstrahierte API, deren Funktionen keinerlei Rückschlüsse auf den verwendeten Persistenzmechanismus
        zulassen. Für EJB läßt sich dies prinzipiell auch realisieren, allerdings müssen für die Variante
        der bean managed persistence innerhalb der Entity Bean die Interaktionen mit dem Persistenzdienstleister
        expliziert werden, beispielsweise durch JDBC. Daher verhält sich dieser Ansatz intern ähnlich zur direkten
        Verwendung der JDBC-API, die inhärent jeden angebundenen Persistenzmechanismus mit relationaler
        Zugriffssemantik belegt.<br/>
        Aufgrund des vorherrschenden relationalen Speicherparadigmas kann die Einbindung bestehender Tabellenstrukturen
        in den API-Mechanismus gewünscht sein. Dies ist ausschließlich mit Ansätzen möglich, welche die
        anwenderdefinierte Strukturierung der Zugriffsausdrücke -- etwa durch die Verwendung von SQL -- gestatten. Dies
        ist ausschließlich für JDBC und EJB (sofern bean managed persistence verwendet wird) möglich; JDO sieht
        dies generell nicht vor.</p>
         <illustration id="jdbcEjbJdoVgl" gfx="dba/jdbcEjbJdo.gif" caption="Vergleich zwischen den diskutierten Persistenztechniken" width="650"/>
         <p>Abschließend lassen sich die vorgestellten Schnittstellen hinsichtlich ihrer Möglichkeiten zur
        Bereitstellung eines transparenten Zugriffs auf den Hintergrundspeicher und der manuellen Eingriffsmöglichkeiten
        zur Kontrolle der Persistenz durch den Programmierer kategorisieren.<br/>
        Prinzipiell läßt sich festhalten, daß diese Eigenschaftstypen konkurrierende Zielsetzungen darstellen.
        So bietet JDBC zweifelsohne die größten Möglichkeiten zum steuernden Eingriff durch den Programmierer, wobei
        dieser Ansatz in der Interaktion auch die größte Menge Wissen des Programmierers über die etablierten
        Speicherstrukturen erfordert. Daher realisiert JDBC generell die geringste Transparenz im Zugriff auf
        den Objektspeicher.<br/>
        Auf der anderen Seite realisiert JDO die größtmögliche Transparenz im Objektzugriff, wobei dieser Freiheitsgrad
        zu generell zu Lasten der Eingriffsmöglichkeiten durch den Programmierer umgesetzt werden.</p>
         <scriptElement type="links" title="Weiterführende Links">
            <link>
               <a href="http://tjdo.sourceforge.net/">TJDO -- eine freie JDO-Implementierung</a>
            </link>
            <link>
               <a href="http://java.sun.com/products/jdo/">JDO @ SUN</a>
            </link>
            <link>
               <a href="http://jdocentral.com/">JDOCentral.com -- Die Anlaufstelle der JDO-Entwickler</a>
            </link>
            <link>
               <a href="http://jcp.org/aboutJava/communityprocess/final/jsr012/index2.html">JDO-Spezifikation</a>
            </link>
         </scriptElement>
      </span>
      <topic name="chap2">Architekturmuster and Umsetzungstechniken</topic>
      <p>Neben den Basistechniken und bisher vorgestellten Schnittstellen zur Realisierung von Persistenz
    finden gegenwärtig eine Reihe von Architekturmustern und Handreichungen zur Umsetzung der Verbindung
    von dauerhafter Datenspeicherung und Anwendungsprogrammierung Einsatz.<br/>
    Ziel dieses Kapitels ist es, ausgewählte Muster an Beispielen vorzustellen und ihren Einsatz in den
    Kontext der im <a href="#chap1">Abschnitt eins</a> eingeführten Schnittstellentechniken zu stellen.
    Hierzu werden die Muster zunächst in drei Abschnitte gegliedert und gleichzeitig im Hinblick auf die durch
    sie angesprochene Problemdomäne kategorisiert.</p>
      <ul>
         <li>Domänenlogik: Muster dieser Klasse dienen dazu, die Verbindung zwischen Applikationslogik und
        persistenter Datenspeicherung zu strukturieren und die beiden Systemebenen wirkungsvoll zu entkoppeln.</li>
         <li>Datenzugriff: Muster dieser Klasse dienen dazu, den Zugriff auf die verwalteten Daten zu abstrahieren
        und diese in einheitlicher Weise zugreifbar werden zu lassen.</li>
         <li>Objekt-Relational-Abbildung und -Interoperabilität:
        Muster dieser Klasse dienen dazu, eine Brücke zwischen objektorientierter Applikationsdatenhaltung
        und heute (noch) vorherrschender relationaler Speicherung zu schlagen.</li>
      </ul>
      <p>Die vorgestellten Muster und Beispiele orientieren sich an den im
    <a href="index.html#patterns">Buch <em>Patterns of Enterprise Application Architecture</em> von
    <name>M. Fowler</name>
         </a>
    vorgestellten.</p>
      <subtopic name="domlog">Domänenlogik</subtopic>
      <p>Die nachfolgend eingeführten Muster zur Abbildung von Datenbank-gestützt operierender
    Applikationslogik in Programmstrukturen. Durch die Anwendung der diskutierten Mechanismen
    wird eine Entkopplung zwischen Datenbankoperationen und Domänen-induzierten Operationen
    der Applikationsebene angestrebt, um diese voneinander separiert entwickeln und modifizieren zu können.</p>
      <subsubtopic name="domlogTS">Transaction Script</subsubtopic>
      <p>
         <b>Motivation und Grundidee</b>: Zur Abbildung komplexer Geschäftsoperationen sind in der Regel
    eine Reihe von eigenständigen Datenbankinteraktionen notwendig.
    Werden einzelne dieser Interaktionen außerhalb ihres logischen
    Kontexts ausgeführt, so kann dies zu Inkonsistenzen des verwalteten Datenbestandes führen.<br/>
    Gleichzeitig setzt die korrekte Ausführung der einzelnen Datenbankoperationen die Kenntnis der Abbildung
    des Geschäftsprozesses auf die technischen Strukturen voraus um gültige Abläufe konstruieren zu können.</p>
      <p>Ziel der Anwendung der <em>Transaktionsskripte</em> (engl. <em>transaction script</em>) ist es jeden
    Geschäftsablauf durch genau eine Applikationsmethode abzubilden, welche die notwendigen Datenbankinteraktionen
    zuverlässig kapselt.<br/>
    Hierbei impliziert der Terminus der <em>Transaktion</em> nicht zwingend die Nutzung von Datenbanktransaktionen
    im Sinne der ACID-Prinzipien.</p>
      <p>
         <b>Struktur</b>: Typischerweise werden die Geschäftsoperationen durch eine oder mehrere Domänenklassen, d.h.
    Klassen deren Struktur und Logik nicht auf Basis technischer Erwägungen und Notwendigkeiten gebildet wurde, zur
    Verfügung gestellt. Diese Klassen treten als Dienstleister gegenüber dem Applikationsprogramm auf.</p>
      <p>
         <illustrationLink ref="Bank"/> zeigt die Grundstruktur des Dienstangebotes einer <code>Bank</code>.
    Sie bietet Überweisungen eines Geldbetrages von einem Konto zum anderen sowie die Möglichkeit der Erstellung
    einer Vermögensübersicht für einen Kunden an.</p>
      <illustration id="Bank" gfx="dba/bank.gif" caption="Dienstangebot der Bank" width="550"/>
      <p>Die verwalteten Daten seien in diesem Beispiel in einer relationalen Datenbank abgelegt, die aus
    zwei Tabellen (<code>Konto</code> und <code>Inhaber</code>) besteht. <illustrationLink ref="BankRel"/>
    zeigt den Datenbankaufbau.</p>
      <illustration id="BankRel" gfx="dba/bankRel.gif" caption="Relationale Struktur der Bank" width="650"/>
      <p>Der Aufbau der Datenbank und ihre Befüllung mit Beispieldaten geschieht durch das folgende SQL-Script:</p>
      <scriptElement type="example" name="createBank.sql" title="Erzeugung und Befüllung der Datenbank mit SQL" filename="createBank.sql">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/createBank.sql"/>
      </scriptElement>
      <p>
         <b>Das Transaktionsskript</b>: Beispiel <scriptRef type="example" name="Bank.java"/> zeigt
    die das Transaktionsskript realisierende Klasse. Sie kapselt die Datenbankinteraktion vollständig und
    stellt die beiden in <illustrationLink ref="Bank"/> gezeigten Methoden zur Verfügung.</p>
      <scriptElement type="example" name="Bank.java" title="Transaktionsskript zur Interaktion mit der Bank" filename="Bank.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/Bank.java"/>
      </scriptElement>
      <p>Die gesamte Interaktion mit der Persistenzlogik geschieht durch die beiden Geschäftsmethoden und
    bedarf keiner Kenntnis und Berücksichtigung der technischen Datenbankcharakteristika. Beispiel
    <scriptRef type="example" name="Driver.java"/> zeigt die Nutzung der beiden angebotenen Methoden.</p>
      <scriptElement type="example" name="Driver.java" title="Nutzung des Transaktionsskriptes" filename="Driver.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/Driver.java"/>
      </scriptElement>
      <p>
         <b>Umsetzung unter Einsatz des <em>Command Musters</em>
         </b>:<br/>
        Die Nutzung von Transaktionsskripten führt zur Bildung von Methoden, die mit Namen aus der Geschäftsdomäne
        belegt sind. So treten im Beispiel <scriptRef type="example" name="Bank.java"/> die Methoden
        <code>Überweisung</code> und <code>Vermögensübersicht</code> auf.<br/>
        Diese Benennungseigenschaft ist jedoch nicht immer gewünscht. Vielmehr strebt man bei der Implementierung
        häufig eine gleichartige Aufrufschnittstelle verschiedener Sachverhalte an. Daher findet sich häufig
        Transaktionsskripte mithilfe des <em>Command Musters</em> umgesetzt.</p>
      <p>Dieses Muster definiert für alle aufrufbaren Domänenmethoden des Transaktionsskriptes eine einheitliche
        Schnittstelle (im Beispiel durch die Methode <code>run</code> verkörpert).<br/>
        Der Einsatz des Musters hat jedoch keinen Einfluß auf die verwirklichte Domänenlogik, sondern ändert nur
        die Aufrufmimik.</p>
      <p>Die Beispiele <scriptRef type="example" name="TransactionScript.java"/> mit
        <scriptRef type="example" name="Vermögensübersicht.java"/> zeigen die modifizierte Umsetzung der
        einzelnen Methoden des Transaktionsskripts, die nun durch separate Klassen repräsentiert werden.
        Die Kontroll-Logik bleibt jedoch gegenüber der vorhergehenden Lösung unverändert.</p>
      <scriptElement type="example" name="TransactionScript.java" title="TransactionScript.java" filename="TransactionScript.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/TransactionScript.java"/>
      </scriptElement>
      <scriptElement type="example" name="Überweisung.java" title="Überweisung.java" filename="Überweisung.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/Überweisung.java"/>
      </scriptElement>
      <scriptElement type="example" name="Vermögensübersicht.java" title="Vermögensübersicht.java" filename="Vermögensübersicht.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/Vermögensübersicht.java"/>
      </scriptElement>
      <p>Bei der Erstellung von Applikationen, welche die vereinheitlichten Schnittstellen nutzen
        zeigt sich das Resultat in Form einer gleichartigen Aufrufschnittstelle
        (im Beispiel die Methode <code>run</code>) für die verschiedenen
        Domänenmethoden:</p>
      <scriptElement type="example" name="Driver2.java" title="Driver2.java" filename="Driver2.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/Driver2.java"/>
      </scriptElement>
      <p>
         <b>Abschließende Würdigung</b>:<br/>
        Das Transaktionsskript-Muster bietet eine vergleichsweise einfach nachvollziehbare Möglichkeit zur
        Entkopplung von Persistenz- und Geschäftslogik an. Jedoch tritt sehr schnell (wie in den Beispielen
        <scriptRef type="example" name="Überweisung.java"/> und <scriptRef type="example" name="Vermögensübersicht.java"/>
        anhand der Methode <code>connectDB</code> gezeigt) die Gefahr auf, daß gleichartiger Code in verschiedene
        Transaktionsskripte zu integrieren ist.<br/>
        Überdies führen komplexe Geschäftslogiken, die sich partiell überlappen und gegenseitig enthalten zu
        aufwendigen Entwürfen in denen Coderedundanz nicht immer zu vermeiden ist.</p>
      <p>Abhilfe kann hier die Verwendung eines <em>Domänenmodells</em> bieten.</p>
      <subsubtopic name="DomainModel">Domain Model</subsubtopic>
      <p>
         <b>Motivation und Grundidee</b>: Hintergrund der Strukturform des <em>Domain Model</em>s ist
        der Versuch die in der Analysephase vorgefundenen Objekte des betrachteten Problembereichs
        möglichst unverändert durch die Applikation zur Verfügung zu stellen und in die Datenbank zu übernehmen.<br/>
        Im Gegensatz zur Strukturierungsform des <em>Transaction Script</em>s erfolgt der Anwendungsaufbau
        hierbei nicht an den Geschäftsprozessen orientiert, sondern rein Daten-getrieben.</p>
      <p>
         <b>Struktur</b>: Im Idealfall entsprechen sich die Struktur der applikationsimmanenten Klassen und
        die der datebankresidenten Tabellen eineindeutig. Abweichungen davon können sich lediglich durch
        Tabellen ergeben, welche dieselbe Realweltentität abbilden. Diese können durch den Normalisierungsprozeß
        gebildet worden sein.<br/>
        Das Beispiel der <illustrationLink ref="domainModelKl"/> zeigt die Klassenstruktur
        einer Projektverwaltung, in der die Zuordnungen zwischen <code>Person</code>en und den <code>Projekt</code>en
        in denen diese eingesetzt sind verwaltet werden.</p>
      <p>Jeder Ausprägung von <code>Person</code> können hierbei mehrere Objekte des Typs <code>Projekt</code>
        zugeordnet sein und umgekehrt.<br/>
        Zusätzlich sind die für die jeweiligen Klassen definierten Operation dargestellt. Hierbei
        kann es sich um triviale Operationen zum Setzen und Auslesen einzelner Attributwerte oder
        beliebig aufwendige Vorgänge handeln. Gemeinsames Kennzeichen aller Operationen ist jedoch,
        daß sie nur dasjenige Objekt betreffen in dessen Kontext sie definiert sind.</p>
      <illustration id="domainModelKl" gfx="dba/domainModelKl.gif" caption="Klassenstruktur der Projektverwaltung" width="628"/>
      <p>Die verwalteten Daten sind in drei Datenbanktabellen abgelegt. <illustrationLink ref="domainModelRel"/> zeigt die Struktur der Tabellen einschließlich
         der definierten Fremdschlüsselbeziehungen.<br/>
         Aus Gründen der Normalisierung (die Relation befindet sich in
         <a href="../datenbanken/script.html#4NFChap">vierter Normalform</a>) wird zusätzlich
         die Tabelle <code>WorksOn</code> eingeführt, welche die Daten über die Zuordnung zwischen
         <code>Projekt</code>en und den sie bearbeitenden <code>Person</code>en enthält.</p>
      <illustration id="domainModelRel" gfx="dba/domainModelRel.gif" caption="Tabellenstruktur der Projektverwaltung" width="600"/>
      <p>Der Aufbau der Datenbank geschieht durch das folgende SQL-Script:</p>
      <scriptElement type="example" name="domainModelRel.sql" title="DB-Aufbau" filename="domainModelRel.sql">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/domainModelRel.sql"/>
      </scriptElement>
      <p>
         <b>Das Domänenmodell</b>: Die Beispiele <scriptRef type="example" name="Person.java"/> und
        <scriptRef type="example" name="Projekt.java"/> zeigen die beiden fachlichen Domänenklassen
        <code>Person</code> und <code>Projekt</code>.</p>
      <scriptElement type="example" name="Person.java" title="Die Domänenklasse Person" filename="domainModel/Person.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/domainModel/Person.java"/>
      </scriptElement>
      <scriptElement type="example" name="Projekt.java" title="Die Domänenklasse Projekt" filename="domainModel/Projekt.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/domainModel/Projekt.java"/>
      </scriptElement>
      <p>Zusätzlich ist aus Gründen der vereinfachten Interaktion mit dem Datenbankmanagementsystem
        die Klasse <code>DBConnector</code> umgesetzt.</p>
      <scriptElement type="example" name="DBConnector.java" title="Die Klasse DBConnector" filename="domainModel/DBConnector.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/domainModel/DBConnector.java"/>
      </scriptElement>
      <p>Die beiden Domänenklassen kapseln die Interaktion mit der Datenbank vollständig
        vor dem Aufrufer. Alle Persistenzoperationen werden in Form einfacher (<gerquot>low-level</gerquot>)
        Operationen zur Verfügung gestellt. Die durch eine Klasse angesprochenen Datenbanktabellen sind
        dabei streng auf diejenigen beschränkt, welche die durch die Klasse verwaltenden Daten aufnehmen.<br/>
        Auffallend ist, daß die Domänenobjekte außer den Attributen, die den Primärschlüssel repräsentieren,
        keine durch Attribute ausgedrückte Eigenschaften besitzen. Diese werden ausschließlich in der
        Datenbank repräsentiert und im Bedarfsfalle angefragt (Beispiel: Realisierung der Methode
        <code>getGeburtsdatum</code> der Klasse <code>Person</code>).<br/>
        Die Begründung hierfür wird bei der Analyse der Zugriffe auf die Tabelle <code>WorksOn</code> offenkundig.
        Da diese Tabelle durch die beiden Domänenobjekte unabhängig voneinander zugegriffen werden kann, würde
        eine (redundante) Datenverwaltung im Hauptspeicher tendenziell zu Konsistenzproblemen mit durch
        das Datenbankmanagementsystem verwalteten Daten führen. </p>
      <p>Einen solchen Fall, der durch die gewählte Umsetzung korrekt behandelt wird, zeigt
        der in Beispiel <scriptRef type="example" name="TestDriver.java"/> wiedergegebene Code:</p>
      <scriptElement type="example" name="TestDriver.java" title="Domänenmodell verwendende Applikation" filename="domainModel/TestDriver.java">
         <importText URI="../life/vorlesung/DB-Anwendungen/examples/domainModel/TestDriver.java"/>
      </scriptElement>
      <p>Im Beispiel werden zunächst Ausprägungen des Typs <code>Person</code> und <code>Projekt</code>
        erzeugt und manipuliert. Hierbei wird für dasselbe <code>Person</code>en-Objekt eine Zuordnung
        dieses Objekts zu einem Projekt vorgenommen und anschließend diesem Projekt eine andere Person
        zugeordnet. Diese beiden Interaktionen entsprechen der Instanziierung der die beiden
        Domänenklassen verbindenden Assoziation mit jeweils unterschiedlichen Ausgangspunkten der
        Beziehungsetablierung.<br/>
        Nur durch den Rückgriff auf die Datenbankinhalte liefert der Aufruf von <code>getAllMitarbeiter</code>
        konsistente Daten, da sowohl innerhalb der <code>Person</code>- als auch der <code>Projekt</code>-Ausprägung
        nur unvollständige (d.h. diejenigen durch den jeweiligen <code>add...</code>-Aufruf erzeugten)
        Daten vorliegen.</p>
      <p>
         <b>Abschließende Würdigung</b>: Das Domänenmodell ermöglicht eine vergleichsweise einfache Abbildung
        der Objektstrukturen des Hauptspeichers in relationale Datenbankstrukturen.<br/>
        Allerdings ist die Abbildung komplexer Abhängigkeitsstrukturen der objektorientierten Applikationsdaten
        in relationale Tabellenstrukturen mitunter schwierig; insbesondere wenn hinsichtlich der Güte der
        entstehenden DB-Strukturen zusätzliche Qualitätskriterien (wie Redundanzfreiheit durch Normalisierung)
        angelegt werden.<br/>
        Grundsätzlich bietet dieses Umsetzungsmuster den Vorteil aus Sicht des Fachanwenders <gerquot>naheliegende</gerquot>
        Entitäten bereitstellen zu können.<br/>
        Die Interaktion auf der Basis der durch Domänenklassen angebotenen Operationen kann, abhängig
        vom Komplexitätsgrad der zu realisierenden Anwendung, -- im Vergleich zum Ansatz des <em>Transaction
        Script</em>s -- aufwendig sein. Insbesondere offenbart sich die vermöge der Domänenoperationen etablierte
        Abstraktionsschicht als Hemmnis, wenn eine direkte Interaktion mit den wertrepräsentierenden
        Tabellen intendiert ist.<br/>
        In diesen Fällen eignet sich ein <em>Table Module</em> besser zur Realisierung.</p>
   </body>
</document>
