Exemple : Utilisation de l'interface locale pour la requête dynamique
Lorsque vous exécutez une requête EJB (Enterprise JavaBeans) dynamique via l'interface locale, vous appelez la méthode executeQuery sur l'interface QueryLocal. Cette dernière ne lance pas de transaction pour la méthode ; il est donc nécessaire d'établir de manière explicite un contexte de transaction pour l'exécution de la requête.
Commencez le code de la requête par les instructions d'importation suivantes :
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;
Rédigez ensuite les instructions de requête sous forme d'une chaîne, comme dans l'exemple suivant qui permet d'extraire les noms et les références d'EJB de salariés sous-payés :
String query = "select e.name, object(e) from EmpBean e where e.salary < 50000 ";
Créez un objet QueryLocal à l'aide d'une référence issue de la classe QueryLocalHome (cette classe définit la méthode executeQuery). A noter que dans l'exemple qui suit, ejb/query est utilisé comme référence d'EJB locale désignant le nom JNDI de la requête dynamique (com/ibm/websphere/ejbquery/Query) :
InitialContext ic = new InitialContext(); QueryLocalHome qh = ( LocalQueryHome) ic.lookup( "java:comp/env/ejb/query" ); QueryLocal qb = qh.create();
La dernière portion du code initie une transaction, appelle la méthode executeQuery et affiche les résultats de la requête. La classe QueryLocalIterator est instanciée car elle définit l'ensemble de résultats de la requête Cette classe est incluse dans le module de l'API Class QueryIterator. L'itérateur perd sa validité à la fin de la transaction ; vous devez donc l'utiliser dans la même portée de transaction que l'appel executeQuery.
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();
Dans la plupart des cas, l'objet QueryLocalIterator fonctionne à la demande. En effet, il renvoie les données de manière incrémentale : pour chaque extraction d'enregistrement de la base de données, la méthode next() doit être appelée sur l'itérateur (il existe des cas où l'itérateur ne fonctionne pas à la demande. Pour plus d'informations, voir la section relatives aux interfaces de requête locales dans Remarques concernant les performances de requête dynamique).
Etant donné que l'ensemble de résultats de la requête se matérialise de manière incrémentale dans le serveur d'applications, il est aisé de contrôler sa taille. Ainsi, lors d'une exécution test vous pouvez décider que seuls quelques nuplets du résultat de la requête sont nécessaires. Dans ce cas, vous devez utiliser un appel de la méthode close() sur l'objet QueryLocalIterator pour fermer la boucle de la requête. Des ressources SQL sont alors libérées et utilisées par l'itérateur. Dans le cas contraire, ces ressources ne sont pas libérées tant que la totalité de l'ensemble de résultats ne s'est pas accumulée en mémoire ou que la transaction ne s'est par terminée.