API de requête EntityManager

L'API EntityManager API propose des méthodes permettant d'interroger les données de la grille qui sont stockées à l'aide de cette même API. Elle permet de créer et d'exécuter des requêtes sur une ou plusieurs entités définies dans eXtreme Scale.

Requête et ObjectMaps pour les entités

WebSphere Extended Deployment v6.1 a introduit une fonction de requête étendue pour les entités stockées dans eXtreme Scale. Ce type de requête permet d'extraire des objets à l'aide d'attributs non clés et d'exécuter des agrégations simples telles que des additions, des moyennes, des minima et des maxima pour toutes les données correspondant à une requête. Les applications construisent des requêtes à l'aide de l'API EntityManager.createQuery. Un objet Query est renvoyé. Vous pouvez également l'interroger pour obtenir les résultats de la requête. Il est aussi possible de personnaliser la requête avant de l'exécuter. La requête est exécutée automatiquement lorsqu'une méthode renvoyant un résultat est appelée.

Figure 1. Interaction de la requête avec les mappes de l'objet ObjectGrid, définition du schéma d'entité et association de celui-ci à une mappe ObjectGrid.
Schéma d'entité associé à un gestionnaire d'entité et de session et à une application

Extraction des résultats d'une requête à l'aide de la méthode getResultIterator

Les résultats d'une requête consistent en une liste d'attributs. Imaginons la requête suivante : select a,b,c from X where y=z. Une liste de lignes contenant a, b et c est renvoyée. Cette liste est stockée dans une mappe de portée transaction, ce qui signifie que vous devez associer une clé artificielle à chaque ligne et utiliser un entier qui augmente à chaque ligne. Cette mappe est obtenue à l'aide de la méthode Query.getResultMap. Elle est associée à EntityMetaData, qui décrit chaque ligne de la mappe associée à celle-ci. Vous pouvez accéder aux éléments de chaque ligne à l'aide de lignes de code semblables à l'exemple qui suit :

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

Extraction des résultats d'une requête à l'aide de getResultMap

Le code suivant présente comment extraire certaines parties des clients correspondant à la requête et montre comment accéder aux lignes de résultats. Si vous utilisez l'objet Query pour accéder aux données, l'identificateur généré pour la ligne de la valeur de type long est masqué. Il est visible uniquement lorsqu'ObjectMap est utilisé pour accéder au résultat. Une fois la transaction terminée, la mappe disparaît. Celle-ci est visible uniquement par la session utilisée, c'est-à-dire, normalement, par l'unité d'exécution qui l'a créée. Pour la clé, elle utilise un bloc de données avec un seul attribut ou une valeur de type long avec l'ID de la ligne. La valeur est un autre bloc de données associé à un attribut pour chaque colonne de l'ensemble de résultats.

Cet exemple de code est présenté ci-dessous :

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

Extraction des résultats d'une requête à l'aide d'un itérateur de résultat d'entité

L'exemple de code suivant présente la requête et la boucle permettant d'extraire chaque ligne de résultat à l'aide des API Map normales. La clé correspondant à la mappe est un bloc de données. Vous devez donc construire l'un des types corrects à l'aide de la méthode createTuple dans keyTuple. Essayez d'extraire toutes les lignes dont l'ID est égal ou supérieur à 0. Lorsque des valeurs null sont renvoyées (indiquant qu'aucune clé n'a été trouvée), la boucle se termine. Définissez le premier attribut de keyTuple en tant que valeur de type long que vous souhaitez rechercher. La valeur renvoyée par get est aussi un bloc de données associé à un attribut pour chaque colonne du résultat de la requête. Extrayez ensuite chaque attribut de la valeur Tuple à l'aide de getAttribute.

Voici un exemple du fragment de code suivant :

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

Une valeur ResultEntityName est indiquée pour la requête. Cette valeur indique au moteur de requête que vous souhaitez projeter chaque ligne vers un objet donné, dans ce cas CustomerQueryResult. La classe suit :

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

Dans le premier fragment, remarquez que chaque ligne de la requête est renvoyée en tant qu'objet CustomerQueryResult plutôt qu'en tant qu'Object[]. Les colonnes de résultat de la requête sont projetées vers l'objet CustomerQueryResult. La projection du résultat est légèrement plus lente lors de l'exécution, mais plus lisible. Les entités du résultat de la requête ne doivent pas être enregistrés avec eXtreme Scale au démarrage. Si elles le sont, une mappe globale de même nom est créée et la requête échoue avec une erreur indiquant que le nom de mappe est en double.