Utilizando o serviço de consulta dinâmica
Há momentos no processo de desenvolvimento em que é possível preferir usar o serviço de consulta dinâmica em vez de o serviço de consulta de Enterprise JavaBeans (EJB) regular (o qual pode ser referido como consulta de implementação). Durante o teste, por exemplo, o serviço de consulta dinâmica pode ser utilizado no tempo de execução do aplicativo, desta forma, você não precisa reimplementar seu aplicativo.
Sobre Esta Tarefa
- Você precisa definir uma consulta de maneira programática no tempo de execução do aplicativo, em vez de defini-la na implementação.
- Você precisa retornar vários campos CMP ou CMR de uma consulta. (As consultas de implementação permitem que apenas um elemento único seja especificado na cláusula SELECT.) Para obter informações adicionais, consulte o tópico Exemplo: Consultas EJB.
- Você deseja retornar uma expressão computada na consulta.
- Você deseja usar métodos de objetos de valor ou métodos de bean na instrução de consulta. Para obter informações adicionais, consulte o tópico Expressões de Caminho.
- Você deseja testar uma consulta do EJB de forma interativa durante o desenvolvimento, mas não deseja implementar o aplicativo repetidamente cada vez que atualizar um localizador ou uma consulta select.
A API de consulta dinâmica é um bean de sessão sem preservação de estado. A utilização dele é semelhante à utilização de qualquer outro bean do aplicativo EJB J2EE. Ela está incluída no com.ibm.websphere.ejbquery do pacote de APIs.
interface remota = com.ibm.websphere.ejbquery.Query
interface remota de início = com.ibm.websphere.ejbquery.QueryHome
interface local = com.ibm.websphere.ejbquery.QueryLocal
interface local de início = com.ibm.websphere.ejbquery.QueryLocalHome
Como ela utiliza menos memória do servidor de aplicativos, a interface local assegura melhor desempenho do EJB global do que a interface remota.
Procedimento
Exemplo
- Usando a interface remota para consulta Dinâmica.
Ao executar uma consulta dinâmica EJB (Enterprise JavaBeans) utilizando a interface remota, você está chamando o método executeQuery na interface Query. O método executeQuery tem um atributo de transação REQUIRED para esta interface; portanto, não você deve estabelecer explicitamente um contexto de transação para a execução da consulta.
Ao executar uma consulta dinâmica EJB (Enterprise JavaBeans) utilizando a interface remota, você está chamando o método executeQuery na interface Query. O método executeQuery tem um atributo de transação REQUIRED para essa interface; portanto, não é necessário estabelecer explicitamente um contexto de transação para a execução da consulta.
Inicie com as seguintes instruções de importação:
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;
Em seguida, grave sua instrução de consulta no formato de uma cadeia, como no exemplo a seguir que recupera os nomes e referências ejb para funcionários com remuneração baixa:
String query = "select e.name as name , object(e) as emp from EmpBean e where e.salary < 50000";
Crie um objeto Query, obtendo uma referência da classe QueryHome. (Essa classe define o método executeQuery.) Observe que por questão de simplicidade, o exemplo a seguir utiliza o nome de JNDI da consulta dinâmica para o objeto Query:
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();
Em seguida, você deve especificar um tamanho máximo para o conjunto de resultados da consulta, que é definido no objeto QueryIterator, que está incluído no QueryIterator da classe. Em seguida, você deve especificar um tamanho máximo para o conjunto de resultados da consulta, que está definido no objeto QueryIterator, que está incluído no pacote de APIs QueryIterator. Este exemplo define o tamanho máximo do conjunto de resultados como 99:
QueryIterator it = qb.executeQuery(query, null, null ,0, 99 );
O iterador contém uma coleta de objetos IQueryTuple, que são registros dos valores da coleta de retorno. Correspondendo aos critérios de nossa instrução de consulta de exemplo, cada tupla desse cenário contém um valor de nome e um valor de objeto(e). Para exibir o conteúdo desse resultado de consulta, utilize o seguinte código: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()); }
A saída do programa pode ser semelhante à seguinte:name Bob emp 1001 name Dave emp 298003 ...
Por último, capture e processe quaisquer exceções. Uma exceção pode ocorrer devido a um erro de sintaxe na instrução de consulta ou de um erro de processamento no tempo de execução. O exemplo a seguir captura e processa estas exceções:} catch (QueryException qe) { System.out.println("Query Exception "+ qe.getMessage() ); }
Manipulando grandes coletas de resultados para a consulta da interface remota
Se pretende que sua consulta retorne uma grande coleta, você tem a opção de programá-la para retornar resultados em várias quantidades menores mais gerenciáveis. Utilize os parâmetros skipRow e maxRow do método remoto executeQuery para recuperar a resposta em partes. Por exemplo:
int skipRow=0; int maxRow=100; QueryIterator it = null; do { it = qb.executeQuery(query, null, null ,skipRow, maxRow ); while (it.hasNext() ) { // display result skipRow = skipRow + maxRow; } } while ( ! it.isComplete() ) ;
- Usando a interface local para consulta Dinâmica.
Ao executar uma consulta dinâmica EJB (Enterprise JavaBeans) utilizando a interface local, você está chamando o método executeQuery na interface QueryLocal. Esta interface não inicia uma transação para o método; portanto, você deve estabelecer explicitamente um contexto de transação para executar a consulta.
Nota: Para estabelecer um contexto de transação, o exemplo a seguir chama os métodos begin() e commit(). Uma alternativa para o uso desses métodos é simplesmente incorporar seu código de consulta em um método EJB executado em um contexto de transação.Inicie seu código de consulta com as instruções de importação a seguir:
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;
Em seguida, grave sua instrução de consulta no formato de uma cadeia, como no exemplo a seguir que recupera os nomes e referências ejb para funcionários com remuneração baixa:
String query = "select e.name, object(e) from EmpBean e where e.salary < 50000 ";
Crie um objeto QueryLocal, obtendo uma referência da classe QueryLocalHome. (Esta classe define o método executeQuery.) Observe que, no exemplo a seguir, ejb/query é utilizado como uma referência EJB local que aponta para o nome de JNDI da consulta dinâmica (com/ibm/websphere/ejbquery/Query):
InitialContext ic = new InitialContext(); QueryLocalHome qh = ( LocalQueryHome) ic.lookup( "java:comp/env/ejb/query" ); QueryLocal qb = qh.create();
A última parte do código inicia uma transação, chama o método executeQuery e exibe os resultados da consulta. A classe QueryLocalIterator é instanciada, porque ela define o conjunto de resultados da consulta. A classe está incluída no pacote de API da Classe QueryIterator. Tenha em mente que o iterador perde a validade no final da transação, você deverá usar o iterador no mesmo escopo da transação que a chamada 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();
Na maioria das situações, o objeto QueryLocalIterator é orientado a demanda. Ou seja, ele faz com que dados sejam retornados de forma incremental: para cada recuperação de registro do banco de dados, o método next() deve ser chamado no iterador. (Podem existir situações em que o iterador não é orientado a demanda. Para obter informações adicionais, consulte a subseção Interfaces de consulta local do tópico Considerações de desempenho de consulta dinâmica.)
Como o conjunto de resultados da consulta completo é incrementalmente materializado na memória do servidor de aplicativos, é possível controlar facilmente seu tamanho. Durante uma execução de teste, por exemplo, é possível decidir que o retorno de apenas algumas tuplas do resultado de pesquisa será necessário. Nesse caso, você deve usar uma chamada do método close() no objeto QueryLocalIterator para fechar o loop da consulta. Fazendo isso, você libera recursos SQL utilizados pelo iterador. Caso contrário, estes recursos não são liberados até o conjunto total de resultados ser acumulado na memória ou até a transação terminar.