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.
