Die API "EntityManager" stellt Methoden für die Abfrage von Daten im ObjectGrid bereit, die mit der API "EntityManager" gespeichert wurden. Die API "EntityManager Query" wird verwendet, um Abfragen über eine oder mehrere in eXtreme Scale definierte Entitäten zu erstellen und auszuführen.
In WebSphere Extended Deployment Version 6.1 wurden erweiterte Abfragefunktionen für Entitäten eingeführt, die in eXtreme Scale gespeichert sind. Mit Hilfe dieser Abfragen können Objekte über Attribute ohne Schlüsselfunktion abgerufen werden und einfache Spaltenberechnungen wie Summe, Durchschnitt, Minimum und Maximum für alle Daten, die einer Abfrage entsprechen, durchgeführt werden. Anwendungen erstellen eine Abfrage über die API "EntityManager.createQuery". Diese Abfrage gibt ein Query-Objekt zurück, das dann abgefragt werden kann, um die Abfrageergebnisse zu erhalten. Das Query-Objekt lässt auch die Anpassung der Abfrage zu, bevor die Abfrage ausgeführt wird. Die Abfrage wird automatisch ausgeführt, wenn eine Methode aufgerufen wird, die das Ergebnis zurückgibt.
Abfrageergebnisse sind eine Liste mit Attributen. Wenn die Abfrage "select a,b,c from X where y=z" lautet, wird eine Liste mit Zeilen zurückgegeben, die a, b und c enthalten. Diese Liste wird in einer transaktionsbezogenen Map gespeichert, d. h., Sie müssen jeder Zeile einen künstlichen Schlüssel zuordnen und eine ganze Zahl verwenden, die mit jeder Zeile um eins steigt. Diese Map wird mit der Methode "Query.getResultMap" abgerufen. Die Map enthält Entitätsmetadaten, die jede Zeile in der zugehörigen Map beschreiben. Sie können auf die Elemente jeder Zeile mit Code wie dem folgenden zugreifen:
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 ]);
}
Der folgende Code veranschaulicht, wie bestimmte Teile der übereinstimmenden Customer-Objekte abgerufen und auf die zurückgegebenen Zeilen zugegriffen wird. Wenn Sie das Query-Objekt für den Zugriff auf die Daten verwenden, wird die generierte Zeilenkennung vom Typ "long" verdeckt. Die Zeilenkennung vom Typ "long" ist nur sichtbar, wenn Sie die ObjectMap für den Zugriff auf das Ergebnis verwenden. Nach Abschluss der Transaktion wird diese Map entfernt. Die Map ist nur für die verwendete Sitzung sichtbar, d. h. normalerweise nur für den Thread, der sie erstellt hat. Die Map verwendet für den Schlüssel ein Tupel mit einem einzigen Attribut vom Typ "long" mit der Zeilen-ID. Der Wert ist ein weiteres Tupel mit einem Attribut für jede Spalte in der Ergebnismenge.
Der folgende Beispielcode veranschaulicht dies:
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));
}
Der folgende Code veranschaulicht die Abfrage und die Schleife, mit denen die einzelnen Ergebniszeilen über die herkömmlichen Map-APIs abgerufen werden. Der Schlüssel für die Map ist ein Tupel. Sie müssen also einen der richtigen Typen mit dem Ergebnis der Methode "createTuple" in "keyTuple" erstellen. Versuchen Sie, alle Zeilen mit Zeile-IDs ab 0 aufwärts abzurufen. Wenn die Abfrage null zurückgibt (d. h., der Schlüssel wurde nicht gefunden), wird die Schleife beendet. Sie definieren, dass das erste Attribut von keyTuple der Wert vom Typ "long" ist, den Sie suchen möchten. Der von der get-Methode zurückgegebene Wert ist ebenfalls ein Tupel mit einem Attribut für jede Spalte im Abfrageergebnis. Anschließend extrahieren Sie mit getAttribute jedes Attribut aus dem Werttupel.
Sehen Sie sich das nächste Codefragement an:
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();
In der Abfrage ist ein ResultEntityName-Wert angegeben. Dieser Wert teilt der Abfragesteuerkomponente mit, dass Sie jede Zeile einem bestimmten Objekt zuordnen möchten, in diesem Fall CustomerQueryResult. Im Folgenden sehen Sie die Klasse:
@Entity
public class CustomerQueryResult {
@Id long rowId;
String id;
String firstName;
String surname;
};
Im ersten Snippet wird jede Abfragezeile als CustomerQueryResult-Objekt und nicht als Object[] zurückgegeben. Die Ergebnisspalten der Abfrage werden dem CustomerQueryResult-Objekt zugeordnet. Die Projektion des Ergebnisses ist zur Laufzeit geringfügig langsamer, aber lesbarer. Abfrageergebnisentitäten sollten beim Start nicht bei eXtreme Scale registriert werden. Wenn die Entitäten registriert werden, wird eine globale Map desselben Namens erstellt, und die Abfrage scheitert mit einem Fehler, der auf den doppelt vorhandenen Map-Namen hinweist.