API EntityManager Query

La API EntityManager proporciona métodos para consultar datos en ObjectGrid almacenados mediante la API EntityManager. La API EntityManager Query se utiliza para crear y ejecutar consultas sobre una o más entidades definidas en eXtreme Scale.

Consulta y ObjectMaps de entidades

WebSphere Extended Deployment v6.1 ha presentado y ampliado la capacidad de consulta para las entidades almacenadas en eXtreme Scale. Estas consultas permiten recuperar objetos utilizando atributos no de clave y realizar agregaciones sencillas como, por ejemplo, sum, average, minimum y maximum en todos los datos que coinciden con una consulta. Las aplicaciones construyen una consulta mediante la API EntityManager.createQuery. Ésta devuelve un objeto Query, que puede después interrogarse para obtener los resultados de la consulta. Con el objeto Query también puede personalizar la consulta antes de ejecutarla. La consulta se ejecuta automáticamente cuando se llama a cualquier método que devuelva el resultado.

Figura 1. La interacción de la consulta con las correlaciones de objeto ObjectGrid y cómo se define y asocia el esquema de entidad con una correlación de ObjectGrid.
El esquema de entidad en asociación con un gestor de sesiones y entidades y una aplicación

Recuperaciones de resultados de consulta utilizando el método getResultIterator

Los resultados de la consulta son una lista de atributos. Si la consulta era seleccionar a,b,c de X donde y=z, se devolverá una lista de filas que contengan a, b y c. Esta lista se almacena en una correlación con ámbito de transacciones, que significa que debe asociar una clave artificial con cada fila y utilizar un entero que aumente con cada fila. Esta correlación se obtiene a través del método Query.getResultMap. La correlación tiene EntityMetaData, que describe cada fila de la correlación asociada con ella. Puede acceder a los elementos de cada fila con un código similar al siguiente:

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 ]);
  }

Recuperación de resultados de la consulta mediante getResultMap

El siguiente código muestra la recuperación de partes específicas de clientes (Customers) coincidentes y muestra cómo acceder a las filas de resultados. Si utiliza el objeto Query para acceder a los datos, el identificador de fila long generado no se muestra. El tipo long sólo se muestra al utilizar ObjectMap para acceder al resultado. Cuando la transacción se completa, esta Map desaparece. La correlación sólo está visible para el objeto Session utilizado, es decir, normalmente sólo para la hebra que la ha creado. La correlación utiliza el tuple para la clave con un atributo único, un tipo long con el ID de fila. El valor es otro tuple con un atributo para cada columna del conjunto de resultados.

Observe el siguiente código de ejemplo:

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));
}

Recuperación de resultados de la consulta mediante un iterador de resultados de entidad

El código siguiente muestra la consulta y el bucle que recupera cada fila de resultado mediante el uso de las API de correlación normales. La clave de la correlación es un tuple. Por lo tanto, si se construye uno de los tipos correctos mediante el método createTuple, resulta en keyTuple. Intente recuperar todas las filas con los ID de fila de 0 en adelante. Cuando get devuelva null (que indica que no se ha encontrado la clave), el bucle termina. Establezca el primer atributo de keyTuple para que tenga la longitud que desea encontrar. El valor devuelto por get también es un tuple con un atributo para cada columna en el resultado de la consulta. Después, extraiga cada atributo del valor Tuple mediante getAttribute.

A continuación se muestra un fragmento de código que ilustra lo descrito:

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 es el ID no el valor de firstName.
  System.out.println("Found a Claus with id " + row.id
    + ", firstName: " + row.firstName
    + ", surname: " + row.surname);
}

em.getTransaction().commit();

Se especificada un valor de ResultEntityName en la consulta. Este valor indica al motor de consultas que desea proyectar cada fila en un objeto específico, CustomerQueryResult en este caso. La clase es la siguiente:

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

En el primer fragmento de código, observe que cada fila de la consulta se devuelve como objeto CustomerQueryResult en lugar de como Object[]. Las columnas de resultado de la consulta se proyectan al objeto CustomerQueryResult. Proyectar el resultado es ligeramente más lento en el tiempo de ejecución, pero más legible. Las entidades del resultado de la consulta no se deben registrar con eXtreme Scale en el arranque. Si las entidades se registran, se crea una correlación global con el mismo nombre y la consulta falla con un error que indica un nombre de correlación duplicado.