Dnes si ukážeme druhý scénář aplikace z minulého dílu.

Pro připomenutí: tvořili jsme Java projekci Caché persistentních tříd a nad výslednými proxy Java třídami jsme prováděli operace projekce z třídy s aplikační logikou, vytvořenou v Caché.

Použijeme tedy stejné persistentní třídy jako minule, včetně jejich projekce do Javy. Ovšem aplikační logiku budeme plně implementovat na straně Javy. K tomu musíme nejdříve vystavit třídy účtů do Javy pomocí projekce, kterou můžeme umístit třeba do třídy ucto.demo.IUcet:

Projection Java As %Projection.Java(ROOTDIR = "C:\Java\netbeans\mojeucto\src\mojeucto\");

Poté zkompilujeme celý projekt. Všimněte si, že ačkoliv ve třídě ucto.demo.Denik nemáme uvedenu deklaraci projekce, přesto se nám vytvoří a to proto, neboť se na ni odkazuje třída Zapis (která ovšem také tuto deklaraci neobsahuje) a tato třída se odkazuje prostřednictvím referenčních atributů na třídu Analytika, do které je projekce vnesena právě z třídy IUcet.

V příkladu využijeme kód s minulého dílu, pouze budeme nově implementovat metodu zauctuj().

Nejjednodušší bude vytvořit novou třídu, např. Main2 a do ní zkopírovat obsah třídy Main z minula s výjimkou právě metody zauctuj().

Než se k tomu dostaneme, ještě strávíme trochu času výkladem o možných způsobech propojení Java klienta a Caché serveru. V metodě connectToCache() z minulého dílu je sestaven objekt CacheConnection voláním CacheDatabase.getDatatase(...). Tomuto způsobu sestavení spojení se říká plná vazba. Existuje též její odlehčená varianta, volaná podobně: CacheDatabase.getLightDatabase(...)

Rozdíl mezi těmito připojeními je následující:

Plná vazba otevírá takové připojení ke Caché serveru, v jehož rámci se objekty otevírané na straně klienta zároveň otevírají i na straně Caché serveru. Ze serveru se na klienta dovážejí hodnoty vlastností, které jsou ve vhodných okamžicích synchronizovány s hodnotami na straně Caché serveru.

Na druhé straně, při použití odlehčené vazby nedochází k inicializaci objektů na straně Caché serveru, ale manipulace s objekty probíhá pomocí SQL kódu, který vzniká automaticky při kompilací persistentních tříd Caché. To má za následek rychlejší vykonání aktualizací dat v databázi, neboť se na straně Caché přistupuje přímo do datových struktur - globálů. Tyto aktualizace jsou ovšem z pohledu klienta stále objektovými operacemi, stále se volají stejné metody vystavených Caché tříd. Na rozdíl od plné vazby ale není možno volat metody instancí neboť, jak bylo uvedeno výše, instance Caché tříd se na serveru nevytvářejí. Odlehčená vazba nabízí vyšší výkon i než případné použití SQL prostřednictvím JDBC rozhraní, neboť kód není nutno dynamicky sestavovat a je též kratší s menším počtem přístupů do globálů.

V praxi je možno ze stejného klienta otevřít jak plné, tak i odlehčené propojení a použít odlehčené propojení pro přímou manipulaci s třídami (změny, vytváření nových instancí, mazání instancí...) a plné spojení pro volání aplikační logiky prezentované metodami instancí Caché tříd.

Pro vyzkoušení si zkuste upravit metodu connectToCache() v minulém díle tak, aby volala getLightDatabase() a spusťte ji. Totéž pak pro srovnání proveďte s níže uvedenou implementací metody zauctuj() v tomto díle.

Nyní si ukažme, jak by mohl kód pro zaúčtování vypadat...

public void zauctuj(String reference, String popis, Double castka, java.sql.Date den, String ucetniPredpis ) {

if(connectToCache(url)) {
try {
int saveResult;

// pro jednoduchost natvrdo predpokladame ze mame k dispozici objekt denik s Id = 1 Denik denik = (ucto.demo.Denik)Denik._open(cacheConnection,new Id(1));
cacheConnection.transactionStart();

Zapis zapis = new Zapis(cacheConnection);
String[] ucty = ucetniPredpis.split("\\|");

String aMaDatiUcet = ucty[0]; String aDalUcet = ucty[1];
String sMaDatiUcet = aMaDatiUcet.substring(0,3); String sDalUcet = aDalUcet.substring(0,3);

Analytika maDati = (ucto.demo.Analytika)Analytika._open(cacheConnection,
new Id(sMaDatiUcet + "||" + aMaDatiUcet));
Analytika dal = (ucto.demo.Analytika)Analytika._open(cacheConnection,
new Id(sDalUcet + "||" + aDalUcet));

zapis.setdenik(denik);
zapis.setdatumZauctovani(den);
zapis.setidentifikace(reference);
zapis.setpopis(popis);
zapis.setcastka(castka);
// pouzijeme ekvivalent $username
zapis.setprovedl("dkutac");
zapis.setnaVrub(maDati);
zapis.setveProspech(dal);
saveResult = zapis.save();

// analytiky
maDati.setnaVrub(maDati.getnaVrub() + castka);
saveResult = maDati.save();

dal.setveProspech(dal.getveProspech() + castka);
saveResult = dal.save();

// syntetiky
Syntetika synMaDati = (ucto.demo.Syntetika)Syntetika._open(cacheConnection,
new Id(sMaDatiUcet));
synMaDati.setnaVrub(synMaDati.getnaVrub()+ castka);
saveResult = synMaDati.save();

Syntetika synDal = (ucto.demo.Syntetika)Syntetika._open(cacheConnection,
new Id(sDalUcet));
synDal.setveProspech(synDal.getveProspech() + castka);
saveResult = synDal.save();

// hotovo
System.out.println("Operace byla v pořádku zaúčtována. (interní číslo zápisu - "
+ zapis.getId() + ")");
cacheConnection.transactionCommit();

cacheConnection.closeAllObjects();
cacheConnection.close();
} catch (Exception ex) {
try {
cacheConnection.transactionRollback();
System.out.println("Transakce byla zrušena!");
} catch (CacheException exRollbackFailed) {
exRollbackFailed.printStackTrace();
}
ex.printStackTrace();
}
} else {
System.out.println("Nelze se připojit ke Caché");
}
}

 

V kódu si všimněte následujících skutečností:

  • Každá metoda Caché třídy je vystavena do Javy pod stejným názvem jako je definována v Caché, s výjimkou tříd začínajících znakem %. Tento znak je v projekcích metod nahrazen podtržítkem. Proto se např. objekty na straně Caché otevírají v Javě některou variantou metody _open(...) zatímco v Caché jsou k dispozici metody %Open() nebo %OpenId().
  • Každá třída vystavená z Caché se otevírá jako RegisteredObject, to je základní třída objektů v Caché.
    K tomu, abychom dostali správný typ třídy, použijeme casting.
  • Při přistupování k vlastnostem Caché tříd vystavených do Javy se důsledně používají přístupové metody.
  • Pro ukládání změn v objektech se volá metoda _save(), kvůli většímu pohodlí vývojářů existuje též i metoda save(). V praxi není třeba zjišťovat výsledek operace save(), jak je to uvedeno v příkladu, neboť pokud vše proběhne v pořádku je výsledek 1, v opačném případě metoda selže a vyhodí výjimku.

V příštím díle se podíváme to, jak pracovat se složitějšími vlastnostmi Caché objektů a jak je možno z Caché řídit způsob jejich vystavení do Javy.