Dynamischen Abfrageservice verwenden

In bestimmten Situationen im Entwicklungsprozess kann es vorteilhaft sein, den dynamischen Abfrageservice anstelle des regulären EJB-Abfrageservice (Enterprise JavaBeans) zu verwenden, der als Implementierungsabfrage bezeichnet werden kann. Beispielsweise kann der dynamische Abfrageservice in der Testphase während der Anwendungsausführung verwendet werden, so dass die Anwendung nicht erneut implementiert werden muss.

Informationen zu diesem Vorgang

Nachfolgend sind häufige Gründe aufgeführt, die für die Verwendung des dynamischen Abfrageservice anstelle des regulären EJB-Abfrageservice sprechen:
  • Sie müssen zur Laufzeit der Anwendung (und nicht während der Implementierung) eine Abfrage über das Programm definieren.
  • Sie müssen mehrere CMP- oder CMR-Felder mit einer Abfrage zurückgeben. (In Implementierungsabfragen darf in der Klausel SELECT nur ein Element angegeben werden). Weitere Informationen finden Sie im Artikel "Beispiel: EJB-Abfragen".
  • Sie möchten einen berechneten Ausdruck in der berechneten Ausdruck in der Abfrage zurückgeben.
  • Sie möchten Methoden für Werteobjekte oder Bean-Methoden in der Abfrageanweisung verwenden. Weitere Informationen finden Sie im Artikel "Pfadausdrücke".
  • Sie möchten eine EJB-Abfrage in der Entwicklungsphase interaktiv testen, aber die Anwendung nicht jedes Mal erneut implementieren, wenn Sie eine Finder- oder Select-Abfrage aktualisieren.

Die Verwendung der API des dynamischen Abfrageservice entspricht im Wesentlichen der Verwendung jeder anderen J2EE-EJB-Anwendungsbean. Sie ist in "com.ibm.websphere.ejbquery" im API-Paket enthalten.

Die dynamische Abfragebean hat eine ferne und eine lokale Schnittstelle. Wenn die Abfrage ferne EJB-Referenzen zurückgegeben soll oder wenn die Abfrageanweisung ferne Methoden enthält, müssen Sie die ferne Schnittstelle für die Abfrage verwenden:

ferne Schnittstelle = com.ibm.websphere.ejbquery.Query
ferne Home-Schnittstelle = com.ibm.websphere.ejbquery.QueryHome

Wenn die Abfrage lokale EJB-Referenzen zurückgegeben soll oder wenn die Abfrageanweisung lokale Methoden enthält, müssen Sie die lokale Schnittstelle für die Abfrage verwenden:

lokale Schnittstelle = com.ibm.websphere.ejbquery.QueryLocal
lokale Home-Schnittstelle = com.ibm.websphere.ejbquery.QueryLocalHome

Eine lokale Schnittstelle bietet eine bessere EJB-Gesamtleistung als eine ferne Schnittstelle, weil es weniger Speicher des Anwendungsservers verbraucht.

Vorgehensweise

  1. Vergewissern Sie sich, dass die Anwendungsdatei "query.ear" in dem Anwendungsserver installiert ist, in dem die Anwendung ausgeführt wird, falls dieser Server nicht der Standardanwendungsserver ist, der während der Installation des Produkts erstellt wurde.
    Die Datei query.ear befindet sich im Verzeichnis Stammverzeichnis_des_Anwendungsservers, wobei <WAS_HOME> für die Position von WebSphere Application Server steht. Das Produktinstallationsprogramm installiert die Datei query.ear mit dem folgenden JDNI-Namen im Standardanwendungsserver:
    com/ibm/websphere/ejbquery/Query
    (Dieser Name kann von Ihnen oder vom Systemadministrator geändert werden.)
  2. Konfigurieren Sie die Berechtigung für die Methoden "executeQuery()", "prepareQuery()" und "executePlan()" in den fernen und lokalen Schnittstellen für dynamische Abfragen, um den Zugriff auf kritische Daten zu steuern. (Dieser Schritt ist nur erforderlich, wenn Ihre Anwendung Sicherheit erfordert.)

    Da Sie nicht steuern können, welche ASN-Namen, CMP-Felder oder CMR-Felder in einer dynamischen EJB-Abfrage verwendet werden, müssen Sie bzw. Ihr Systemadministrator die Verwendung der Methoden beschränken. Wenn ein Benutzer beispielsweise für die Methode executeQuery berechtigt ist, kann er jede gültige dynamische Abfrage ausführen. Für Produktionsumgebungen ist eine Beschränkung des Zugriffs auf die Methoden der fernen Schnittstelle auf jeden Fall zu empfehlen.

  3. Schreiben Sie die dynamische Abfrage in Ihrem Anwendungsclientcode. Sie können die Artikel mit den Beispielen für dynamische Abfrage über eine ferne Schnittstelle und dynamische Abfrage über eine lokale Schnittstelle als Abfragemodelle verwenden. In diesen Artikeln wird veranschaulicht, welche Importanweisungen verwendet werden müssen.
  4. Wenn sich die abzufragende CMP-Bean in einem anderen Modul befindet, gehen Sie wie folgt vor:
    1. Führen Sie eine ferne Lookup-Operation für die Datei query.ear aus.
    2. Ordnen Sie die Datei query.ear dem Server zu, in dem die abgefragte CMP-Bean installiert ist.
  5. Kompilieren und führen Sie Ihr Clientprogramm mit der Datei qryclient.jar im Klassenpfad aus.

Beispiel

Ferne Schnittstelle für dynamische Abfrage verwenden

Bei der Ausführung einer dynamischen EJB-Abfrage (Enterprise JavaBeans) über die ferne Schnittstelle wird die Methode "executeQuery" in der Schnittstelle "Query" aufgerufen. Die Methode "executeQuery" hat für diese Schnittstelle das Transaktionsattribut REQUIRED. Deshalb muss nicht explizit ein Transaktionskontext für die Abfrage erstellt werden.

Bei der Ausführung einer dynamischen EJB-Abfrage (Enterprise JavaBeans) über die ferne Schnittstelle wird die Methode "executeQuery" in der Schnittstelle "Query" aufgerufen. Die Methode "executeQuery" hat für diese Schnittstelle das Transaktionsattribut REQUIRED. Deshalb muss nicht explizit ein Transaktionskontext für die Abfrage erstellt werden.

Beginnen Sie mit den folgenden Importanweisungen:

import com.ibm.websphere.ejbquery.QueryHome;
import com.ibm.websphere.ejbquery.Query;
import com.ibm.websphere.ejbquery.QueryIterator;
import com.ibm.websphere.ejbquery.IQueryTuple;
import com.ibm.websphere.ejbquery.QueryException;

Schreiben Sie anschließend Ihre Abfrageanweisung in Form einer Zeichenfolge. Das folgende Beispiel ruft beispielsweise die Namen und EJB-Referenzen für unterbezahlte Mitarbeiter auf:

String query = 
"select e.name as name , object(e) as emp from EmpBean e where e.salary < 50000"; 

Erstellen Sie ein Query-Objekt, indem Sie eine Referenz von der Klasse QueryHome anfordern. (Diese Klasse definiert die Methode executeQuery.) Zur Vereinfachung verwendet das folgende Beispiel den JNDI-Namen für dynamische Abfragen für das Query-Objekt:

InitialContext ic = new InitialContext();

Object obj =  ic.lookup("com/ibm/websphere/ejbquery/Query");

QueryHome  qh = 
 ( QueryHome) javax.rmi.PortableRemoteObject.narrow( obj, QueryHome.class );
Query qb = qh.create();

Anschließend müssen Sie die maximale Größe für die Abfrageergebnismenge festlegen, die in dem in der Klasse "QueryIterator" enthaltenen Objekt "QueryIterator" definiert ist. Anschließend müssen Sie die maximale Größe für die Abfrageergebnismenge festlegen, die in dem im API-Paket "QueryIterator" enthaltenen Objekt "QueryIterator" definiert ist. Dieses Beispiel setzt die maximale Größe für das Abfrageergebnis auf 99:

QueryIterator it = qb.executeQuery(query, null, null ,0, 99 );
Der Iterator enthält eine Sammlung von IQueryTuple-Objekten, die Datensätze der zurückgegebenen Objektgruppenwerte sind. Den Kriterien der Beispielabfrageanweisung entsprechend, enthält jedes Tupel in diesem Szenario einen Wert name und einen Wert object(e). Verwenden Sie zum Anzeigen des Inhalts des Abfrageergebnisses folgenden Code:
while (it.hasNext()) { 
	IQueryTuple tuple = (IQueryTuple) it.next();
	System.out.print( it.getFieldName(1) );
	String s = (String) tuple.getObject(1);
	System.out.println( s);
	System.out.println( it.getFieldName(2) );
	Emp e = ( Emp) javax.rmi.PortableRemoteObject.narrow( tuple.getObject(2), Emp.class );
	System.out.println( e.getPrimaryKey().toString());
}
Die Ausgabe des Programms könnte wie folgt aussehen:
name Bob 
emp 1001
name Dave
emp 298003
...
Abschließend müssen alle Ausnahmen abgefangen und behandelt werden. Eine Ausnahme kann eintreten, wenn eine Abfrageanweisung einen Syntaxfehler enthält oder wenn zur Laufzeit ein Verarbeitungsfehler auftritt. Das folgende Beispiel fängt diese Ausnahmen ab und behandelt sie:
} catch (QueryException qe) {
    System.out.println("Query Exception "+ qe.getMessage() );
}

Verarbeitung umfangreicher Ergebnismengen für Abfragen mit der fernen Schnittstelle

Wenn Ihre Abfrage umfangreiche Ergebnismengen zurückgegeben soll, können Sie die Abfrage so programmieren, dass die Ergebnisse in mehreren kleineren, besser verwaltbaren Einheiten zurückgegeben werden. Verwenden Sie die Parameter "skipRow" und "maxRow" der fernen Methode "executeQuery", um die Antwort in Blöcken abzurufen. Beispiel:

int skipRow=0;
int maxRow=100;
QueryIterator it = null;
do {
		it = qb.executeQuery(query, null, null ,skipRow, maxRow );
	while (it.hasNext()) { 
	// Ergebnis anzeigen
		skipRow = skipRow + maxRow;
}
} while ( ! it.isComplete() ) ;
Lokale Schnittstelle für dynamische Abfrage verwenden

Bei der Ausführung einer dynamischen EJB-Abfrage (Enterprise JavaBeans) über die lokale Schnittstelle wird die Methode "executeQuery" in der Schnittstelle "QueryLocal" aufgerufen. Diese Schnittstelle leitet keine Transaktion für die Methode ein. Deshalb müssen Sie für die Abfrage explizit einen Transaktionskontext einrichten.

Anmerkung: Zum Einrichten eines Transaktionskontextes ruft das folgende Beispiel die Methoden begin() und commit() auf. Alternativ zur Verwendung dieser Methoden können Sie Ihren Abfragecode auch einfach in eine EJB-Methode einbetten, die in einem Transaktionskontext ausgeführt wird.

Beginnen Sie den Abfragecode mit den folgenden Importanweisungen:

import com.ibm.websphere.ejbquery.QueryLocalHome;
import com.ibm.websphere.ejbquery.QueryLocal;
import com.ibm.websphere.ejbquery.QueryLocalIterator;
import com.ibm.websphere.ejbquery.IQueryTuple;
import com.ibm.websphere.ejbquery.QueryException;

Schreiben Sie anschließend Ihre Abfrageanweisung in Form einer Zeichenfolge. Das folgende Beispiel ruft beispielsweise die Namen und EJB-Referenzen für unterbezahlte Mitarbeiter auf:

String query = 
"select e.name, object(e) from EmpBean e where e.salary < 50000 ";

Erstellen Sie ein QueryLocal-Objekt, indem Sie eine Referenz von der Klasse QueryLocalHome anfordern. (Diese Klasse definiert die Methode executeQuery.) Im folgenden Beispiel wird ejb/query als lokale EJB-Referenz verwendet, die auf den JNCI-Namen für dynamische Abfragen (com/ibm/websphere/ejbquery/Query) verweist:

InitialContext ic = new InitialContext();
   QueryLocalHome  qh =  ( LocalQueryHome) ic.lookup( "java:comp/env/ejb/query" );
QueryLocal qb = qh.create();

Der letzte Teil des Codes leitet eine Transaktion ein, ruft die Methode executeQuery auf und zeigt die Abfrageergebnisse an. Die Klasse QueryLocalIterator wird instanziert, weil sie das Abfrageergebnis definiert. Diese Klasse ist im API-Paket der Klasse "QueryIterator" enthalten. Der Iterator verliert am Ende der Transaktion seine Gültigkeit. Sie müssen den Iterator im selben Transaktionsbereich wie den Aufruf executeQuery verwenden.

userTransaction.begin();
QueryLocalIterator it = qb.executeQuery(query, null, null);
while (it.hasNext()) { 
	IQueryTuple tuple = (IQueryTuple) it.next();
	System.out.print( it.getFieldName(1) );
	String s = (String) tuple.getObject(1);
	System.out.println( s);
	System.out.println( it.getFieldName(2) );
	EmpLocal e = ( EmpLocal ) tuple.getObject(2);
	System.out.println( e.getPrimaryKey().toString());
}
userTransaction.commit();

In den meisten Fällen ist das QueryLocalIterator-Objekt bedarfsgesteuert, d. h. die Daten werden inkrementell zurückgegeben. Für jeden Abruf eines Datensatzes aus der Datenbank muss die Methode next() für den Iterator aufgerufen werden. (Es gibt Situationen, in denen der Iterator nicht bedarfsgesteuert ist. Nähere Informationen hierzu finden Sie im Teilabschnitt "Lokale Abfrageschnittstellen" des Artikels Hinweise zur Leistung des dynamischen Abfrageservice.)

Da das vollständige Abfrageergebnis inkrementell im Speicher des Anwendungsservers abgelegt wird, können Sie die Größe problemlos steuern. Während eines Testlaufs können Sie beispielsweise feststellen, dass nur ein paar Tupel des Abfrageergebnisses erforderlich sind. In diesem Fall können Sie mit einem Aufruf der Methode "close()" für das Objekt "QueryLocalIterator" die Abfrageschleife schließen. Damit werden die vom Iterator verwendeten SQL-Ressourcen freigegeben. Andenfalls werden diese Ressourcen erst freigegeben, wenn sich die gesamte Ergebnisobjektgruppe im Speicher befindet oder die Transaktion endet.


Symbol, das den Typ des Artikels anzeigt. Taskartikel



Symbol für Zeitmarke Letzte Aktualisierung: 25.05.2016
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tque_dynamic
Dateiname:tque_dynamic.html