Náš model aplikace je již dost rozsáhlý na to, abychom nad jeho třídami mohli začít provádět dotazování. Dnes si tedy ukážeme, jaké nám Caché nabízí možnosti práce s dotazy na data, vracející sady záznamů.

Jedním z častých dotazů v účetních aplikacích je přehled zůstatků na účtech syntetické evidence, nebo přehled pohybů na účtech - deník. Ukážeme si též, jak lze v Caché tvořit uložené procedury a jak s nimi z Javy pracovat (i když je to z pohledu objektového programování samozřejmě krok zpátky, protože s Caché umí Java spolupracovat objektově, ale někdy se relační způsob může hodit.)

Samozřejmě, že dotazovat se na data v Caché můžeme pomocí SQL i dynamicky, ale v takovém případě musí server, pokud nemá již vygenerovaný runtime kód našeho SQL dotazu nakešován, nejdříve příslušný kód sestavit, což jej může zdržovat. Proto je vhodné, alespoň u často používaných dotazů, tyto nadefinovat jako součást definice třídy, a tedy se stanou částí API aplikace.

Ukážeme si, jak sestavit sadu záznamů se zůstatky na účtech syntetické evidence.

V Caché Studiu otevřeme třídu ucto.demo.Syntetika k editování. Pomocí průvodce přidáním dotazu (menu Class -> Add -> New Query) nadefinujeme seznam vstupních parametrů dotazu (v našem případě žádné nebudou) a poté vybereme, zda náš dotaz bude tvořen SQL příkazem nebo kódem v některém ze skriptovacích jazyků Caché; zvolíme SQL, sestavu nazveme OsnovaReport.

Definice dotazu bude vypadat takto:

Query OsnovaReport() As %SQLQuery(CONTAINID = 1)
{
SELECT %ID,cisloUctu,nazev,typ,aktualniZustatek as zustatek FROM ucto_demo.Syntetika
ORDER BY cisloUctu
}

Vidíte, že je to klasický SQL dotaz. Jediné co Vás může zarazit, je parameter CONTAINID=1, ten říká, že dotaz vrací identifikátor objektu (jako %ID) a pro náš příklad není důležitý. Tento parametr je používán jinými technologiemi. ID se však hodí pro následné otevírání instancí objektů.

Po zkompilování třídy a vytvoření aktualizované verze Java proxy třídy se dotaz stane součástí Java projekce. Caché dotazy jsou vystaveny jako statické metody vracející třídu CacheQuery. Následující řádky ukazují jednoduchý kód volající výše definovaný dotaz:

String url="jdbc:Cache://localhost:56773/" + namespace;
dbconnection = CacheDatabase.getDatabase (url, username, password);
System.out.println( "Spojeno." );

CacheQuery qry = Syntetika.query_OsnovaReport(dbconnection);
rs = qry.execute();
// hlavicka
String h = "";
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
if (i>1) h += ": ";
h += rs.getMetaData().getColumnName(i);
}
System.out.println(h);

while (rs.next()) {
/* vypiseme vsechny sloupce kazdeho nalezeneho radku */
String s = "";
for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
if (s.length() > 0) {
s += ": ";
}
s += rs.getString( i );
}
System.out.println( s );
}
/* Close the ResultSet object */
rs.close();

V předminulém díle našeho seriálu jsme používali metodu _open k otevírání instancí Caché tříd. Tato metoda ovšem předpokládá, že známe identifkátor instance. My jsme před chvíli viděli, jak si identifikátory instancí objektů vrátit; pomocí dotazu. Ovšem existuje i pohodlnější způsob než samostatné volání dotazu a následné použití vráceného ID pro použití v metodě _open, a to metoda OpenByQuery, která kombinuje oba kroky - nalezení ID a otevření objektu.

Ukázka otevření instance syntetického účtu s číslem 221:

Iterator it = Syntetika.openByQuery(dbconnection,"cisloUctu = ?", 
new String[] {"221"});
// vime (cisloUctu je unikatni), ze pokud najdeme nejaka data, tak nanejvys jeden zaznam
if (it.hasNext()) {
Syntetika syn = (Syntetika)it.next();
System.out.println(syn.getcisloUctu() + " : " + syn.getnazev() + " : zustatek: " + syn.getaktualniZustatek());
}

Možná si ještě vybavíte, ze na počátku tohoto seriálu, v jednom z dílů věnovaných technologii Jalapeno, jsme tuto metodu používali také.

V tomto případě se sice SQL dotaz generuje dynamicky, ale jelikož se jedná o prostý select z jedné tabulky, režie na jeho sestavení je minimální.

Když už jsme u dotazování: vzhledem k tomu, že Caché plně podporuje SQL, je možno použít standardní SQL dotazy prostřednictvím JDBC rozhraní. Na tom není nic objevného, takže si to ukazovat nebudeme. Ale ukážeme si, jak lze v Caché označit metodu nebo dotaz jako uloženou proceduru SQL pro volání (nejen) z Javy nikoliv prostřednictvím objektové vazby, ale prostřednictvím JDBC.

Udělat z vloženého dotazu nebo statické metody třídy Caché uloženou proceduru, je velice jednoduché. Stačí přidat k deklaraci metody či dotazu klíčové slovo SQLProc a případně volitelný název uložené procedury. (Stále pracujeme s definicí Caché třídy ucto.demo.Syntetika)

Query Osnova() As %SQLQuery(CONTAINID = 1) [ SqlName = spOsnova, SqlProc ]
{
SELECT %ID,cisloUctu,nazev,typ,{FN CONCAT(aktualniZustatek,' Kč')} as zustatek FROM ucto_demo.Syntetika
ORDER BY cisloUctu
}

Uloženou proceduru pak spustíme jednoduše:

String url="jdbc:Cache://localhost:56773/" + namespace;
Class.forName ("com.intersys.jdbc.CacheDriver");
dbconnection = DriverManager.getConnection(url,username,password);
CallableStatement cs = dbconnection.prepareCall("{call ucto_demo.spOsnova()}");
ResultSet rs = cs.executeQuery();

ResultSetMetaData rsmd = rs.getMetaData();

Příště se pustíme do projekcí Caché tříd do Enterprise Java Beans.