API de Consulta EntityManager

A API do EntityManager fornece métodos para consultar dados no ObjectGrid armazenado utilizando a API do EntityManager. A API de Consulta EntityManager é usada para criar e executar consultas sobre uma ou mais entidades definidas no eXtreme Scale.

Consulta e ObjectMaps para Entidades

O WebSphere Extended Deployment v6.1 introduziu um recurso de consulta avançado para entidades armazenadas no eXtreme Scale. Essas consultas permitem que os objetos sejam recuperados utilizando os atributos não-chave e executem agregações simples, como sum, average, minimum e maximum junto a todos os dados que correspondem a uma consulta. Os aplicativos constroem uma consulta utilizando a API EntityManager.createQuery. Isso retorna um objeto de consulta e pode, então, ser interrogado para obter os resultados da consulta. O objeto de consulta também permite que a consulta seja customizada antes de executá-la. A consulta é executada automaticamente quando qualquer método que retorna o resultado é chamado.

Figura 1. A interação da consulta com os mapas de objetos ObjectGrid e como o esquema da entidade é definido e associado com um mapa ObjectGrid.
Esquema da entidade em associação com uma sessão e gerenciador de entidades e aplicativo

Recuperando resultados da consulta usando o método getResultIterator

Os resultados da consulta são uma lista de atributos. Se uma consulta foi selecionar a,b,c de X, em que y=z, então, uma lista de linhas contendo a, b e c é retornada. Essa lista é armazenada em um Mapa de transações com escopo definido, o que significa que é necessário associar uma chave artificial com cada linha e utilizar um inteiro que aumenta com cada linha. Este mapa é obtido usando o método Query.getResultMap. O mapa possui EntityMetaData, que descreve cada linha no Mapa associado a ele. É possível acessar os elementos de cada linha utilizando o código semelhante ao seguinte:

Query q = em.createQuery("select c.id, c.firstName, c.surname from Customer c where c.surname=?1");

  q.setParameter(1, "Claus");

  Iterator iter = q.getResultIterator();
  while(iter.hasNext())
  {
    Object[] row = (Object[])iter.next();
    System.out.println("Found a Claus with id "  + row[objectgrid: 0 ]
      + ", firstName: " + row[objectgrid: 1 ]
      + ", surname: " + row[objectgrid: 2 ]);
  }

Recuperando Resultados da Consulta Utilizando getResultMap

O código a seguir mostra a recuperação de partes específicas dos Clientes correspondentes e mostra como acessar as linhas resultantes. Se você utilizar o objeto Query para acessar os dados, então o identificador de linha longa gerado será ocultado. O Long é visível somente ao utilizar o ObjectMap para acessar o resultado. Quando a transação é concluída, este mapa desaparece. O Mapa está visível apenas na Session utilizada, ou seja, geralmente apenas no encadeamento que o criou. O Mapa utiliza uma Tupla para a chave com um único atributo, um Long com o ID da linha. O valor é uma outra tupla com um atributo para cada coluna no conjunto de resultados.

O código de amostra a seguir demonstra isto:

Query q = em.createQuery("select c.id, c.firstName, c.surname from
Customer c where c.surname=?1");
q.setParameter(1, "Claus");
ObjectMap qmap = q.getResultMap();
Tuple keyTuple = qmap.getEntityMetadata().getKeyMetadata().createTuple();
for(long i = 0; true; ++i)
{
  keyTuple.setAttribute(0, new Long(i));
  Tuple row = (Tuple)qmap.get(keyTuple);
  if(row == null) break;
  System.out.println(" I Found a Claus with id "  + row.getAttribute(0)
    + ", firstName: " + row.getAttribute(1)
    + ", surname: " + row.getAttribute(2));
}

Recuperando Resultados da Consulta Utilizando um Agente Iterativo de Resultado da Entidade

O código a seguir mostra a consulta e o loop que recupera cada linha resultante utilizando as APIs de mapas normais. A chave para o Mapa é uma Tupla. Portanto, construa uma dos tipos corretos utilizando o resultado do método createTuple em keyTuple. Tente recuperar todas as linhas com rowIds de 0 em diante. Quando você obtém retornos de nulo (indicando que a chave não foi localizada), então o loop é finalizado. Configure o primeiro atributo de keyTuple como o long que deseja localizar. O valor retornado por get também é uma Tupla com um atributo para cada coluna no resultado da consulta. Em seguida, empurre cada atributo da Tupla de valor utilizando getAttribute.

A seguir está o próximo trecho de código:

Query q2 = em.createQuery("select c.id, c.firstName, c.surname from Customer c where c.surname=?1");
q2.setResultEntityName("CustomerQueryResult");
q2.setParameter(1, "Claus");

Iterator iter2 = q2.getResultIterator(CustomerQueryResult.class);
while(iter2.hasNext())
{
  CustomerQueryResult row = (CustomerQueryResult)iter2.next();
  // firstName is the id not the firstName.
  System.out.println("Found a Claus with id " + row.id
    + ", firstName: " + row.firstName
    + ", surname: " + row.surname);
}

em.getTransaction().commit();

Um valor de ResultEntityName está especificado na consulta. Este valor informa ao mecanismo de consulta que você deseja projetar cada linha para um objeto específico, CustomerQueryResult, neste caso. A classe é a seguinte:

@Entity
public class CustomerQueryResult {
	@Id long rowId;
	String id;
	String firstName;
	String surname;
};

No primeiro snippet, observe que cada linha da consulta é retornada como um objeto CustomerQueryResult em vez de um Object[]. As colunas resultantes da consulta são projetadas para o objeto CustomerQueryResult. Projetar o resultado é ligeiramente mais lento no tempo de execução, porém mais legível. O resultado da consulta Entities não deve ser registrado com o eXtreme Scale na inicialização. Se as entidades são registradas, então um Mapa global com o mesmo nome é criado, e a consulta falha com um erro indicando nome de Mapa duplicado.