Oracle C++ Call Interface – 2. First contact, hups connect.
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Oracle C++ Call Interface – 2. First contact, hups connect.Oracle C++ Call Interface – 2. First contact, hups connect.

 

Oracle C++ Call Interface – 2. First contact, hups connect.

Google       Google       25. 8. 2007       19 311×

Tak sa stretávame opäť. Snáď to netrvalo tak dlho že ste už zo svojho PC ORACLE 10g EXPRESS odinštalovali. V tomto dieli sa konečne dostaneme k C++. Najprv si však nastavíme kompilátor tak, aby nám úspešne všetko zlinkoval a skompiloval. Potom si vytvorime spojenie z ORACLE XE a povieme v skratke niečo o TNS.

Kedže seriálom chcem osloviť ako Windows, tak Linux užívateľov, problematiku linkovania teda rozdelím na 2 kapitoly ktorých cieľom bude vytvoriť našu prvú aplikáciu ktorá bude použivať OCCI. Ak ste používateľom OS Windows, tak bude pre vás zaujímavá hlavne prvá kapitola. Pre Linux pozitívnych je určená kapitola druhá. A ak ste moc zvedaný ako to v skutočnosti funguje, tak si prečítajte obe.

OCCI je akýsi vylepšený C++ Wrapper. Čo to znamená? Je to súbor tried postavených nad OCI API. A čo je teraz OCI API? OCI API je súbor funkcií ktoré nám poskytujú prístup do ORACLE XE. Avšak mi priamo z OCI API nebudeme pracovať.

Začiatok na OS Windows

Budem predpokladať že používate vývojové prostredie Visual C++ Express. Keď už Express tak všetko Express. Začneme obligátne. Vytvorime si prázdny projekt konzolovej aplikácie. Pri vytváraní doporučujem vypnúť možnosť precompiled headers. Do projektu si pridáme súbor main.cpp ktorého obsah bude nasledujúci:

main.cpp:

#include <occi.h>

using namespace oracle::occi;

int main()
{
	Environment *env = Environment::createEnvironment();
	Environment::terminateEnvironment(env);	
	return 0;
}

Je to minimálny kód, ktorý na začiatku inicializuje OCCI enviroment a následne ho aj uvoľní. Od tohto OCCI enviromentu sa bude odvíjať ďalšia činnosť, ako napríklad pripojenie na DB a je základom úspešného spustenia programu.

Keď sa pokúsime program skompilovať, tak narazíme na rôzne chyby typu neznámy header, neznáma funkcia. Preto je ešte potrebné nastaviť vo VC++ cesty ku knižniciam, cesty k headerom a nakoniec nastaviť v našom projekte knižnice, ktoré budeme linkovať. Nič strašidelné. Cesty si nastavíme tak, že si otvorime nastavenia VC++ ktoré nájdeme v Tools->Options. Vyberieme si VC++ Direciories. V Include files nastavíme cestu na C:\oracleexe\app\oracle\product\10.2.0\server\OCI\include. V Library files zase nastavíme cestu k C:\oracleexe\app\oracle\product\10.2.0\server\OCI\lib\MSCV. Teraz si klikneme na nastavenia projektu. Vyberieme si Linker-Command Line do ktorého dopíšeme knižnice oraocci10.lib oci.lib ociw32.lib.




Teraz sa už projekt bude dať skompilovať a po úspešnej kompilácii aj spustiť. Podarilo sa? Ak nie tak si prekontrolujte či sa na daných adresách skutočne nachádzajú potrebné *.lib a *.h súbory.

Začiatok na Linuxoch

V tejto kapitole sa budem vyjadrovať trosku komplikovanejšie. Začiatočníckom doporučujem naštudovať ako prebieha kompilácia, čo sú to Makefiles. Bez toho im táto kapitola bude pripadať ako mimozemská reč. Ak si ešte niečo pamätáte z predchádzajúceho dielu, tak slovo ORACLE_HOME vám bude povedomé. Je to cesta k ORACLE XE súborom a pevne verím že ju už máte nastavenú. Tu sa totižto nachádzajú potrebné knižnice a ich headre. To je asi všetko čo k tomu budeme potrebovať.

  • Najprv bude potrebné povedať kompilátoru kde sa nachádzajú headre:

-I$(ORACLE_HOME)/includes

  • Na to aby sme úspešne zlinkovali aplikáciu, je potrebne linkeru povedať, čo ma linkovať:

-I -L$(ORACLE_HOME)/lib -locci -l

  • Takže z toho si vytvorime nasledujúci Makefile:

out : main.cpp
   g++ -I$(ORACLE_HOME)/rdbms/public -L$(ORACLE_HOME)/lib -locci -lclntsh -lnnz10 -o out main.cpp

clean:
   rm -rf out

Teraz to všetko otestujeme. Vytvorime si main.cpp do ktorého vložíme ten istý kód ako v prechádzajúcej kapitole:

main.cpp

#include <occi.h>

using namespace oracle::occi;

int main()
{
   Environment *env = Environment::createEnvironment();
   Environment::terminateEnvironment(env);
   return 0;
}

Ten kompilujeme pomocou make-u a spustíme ho. Nemali by sme obdržať žiadnu chybovú hlášku. Ak by sa tak predsa len stalo, skontrolujte nastavenie ORACLE_HOME a existenciu potrebných knižníc. Taktiež môže nastať situácia, kedy kompilácia prebehla úspešne, ale po spustení ste zhliadli pre mňa veľmi obľúbene hlásenie:

./out: error while loading shared libraries: libocci.so.10.1: cannot open shared object file: No such file or directory

V tomto prípade si skontrolujte či sa vo vašom LD_LIBRARY_PATH nachádza cesta k ORACLE_HOME/lib. V prípade Ubuntu som sa stretol s prípadmi, že LD_LIBRARY_PATH bol správne zadefinovaný, no aj tak to hlásenie nie a nie zmiznúť. Ak máte rovnaký problém, skúste sa pozrieť do /etc/ld.so.conf, či sa tam nachádza cesta k ORACLE_HOME/lib/. V prípade absencie ju tam dopíšte.

Okrem tejto chyby sa môžete stretnúť ešte s jedným problémom. V prípade že používate GCC kompilátor 3.4.x a novší, programy sa vám môžu chovať zvláštne. Knižnica OCCI, ktorá je súčasťou ORACLE 10g Express je kompilovaná pre verziu 3.2.x čím sa stáva nekompatibilná s novšími kompilátormi. Preto je potrebné stiahnuť si prekompilované knižnice. Tie nájdete na www.oracle.com.

Vytvorenie spojenia a trieda Connection

Ak ste sa dostali bez problémov až sem, tak vám gratulujem. Konečne máte za sebou všetky nastavovania a ďalej vás už nečaká nič iné len programovanie. Ak chceme pracovať z ORACLE XE, tak sa najprv musíme k nej pripojiť a prihlásiť. Je to ten istý princíp ako keď používate web rozhranie. Najprv sa pripojíte na web rozhranie, potom sa prihlásite a až po úspešnom prihlásení môžete s ORACLE XE pracovať. Podobne je to aj v C++ aplikáciach.

main.cpp

#include <iostream>
#include <occi.h>

using namespace std;
using namespace oracle::occi;

#define USER  "SYSTEM"
#define PASS  "****"
#define DB    ""

int main()
{
   Environment* env;
   Connection*  con;

   try {
      //vytvorenie spojenia
      env = Environment::createEnvironment();
      con = env->createConnection(USER, PASS, DB);

      //ukoncenie spojenia
      env->terminateConnection(con);
      Environment::terminateEnvironment(env);

   } catch (SQLException e) {
      cout << "ORACLE ERROR:" << e.getErrorCode() << " - " << e.getMessage() << endl;
   }

   return 0;
}

Najprv vytvorime OCCI enviroment. Tento enviroment sa stará o vytvorenie spojení, autentifikáciu a korektné ukončenie spojení. Samozrejme enviroment toho dokáže viac ale nás bude momentálne zaujímať tato jeho funkcionalita. Funkcia createConnection() sa pokúsi vytvoriť spojenie a autentifikovať užívateľa. Ak sa to podarí, funkcia vráti ukazovateľ na Connection. Trieda Connection ďalej len identifikuje vytvorené spojenie. Je dôležité si uvedomiť, že spojenie nevzniká a nezaniká v triede Connection. Spojenie je nakoniec ukončene opäť cez enviroment pomocou terminateConnection(). Trieda Connection len spojenie identifikuje a umožňuje ďalšiu prácu. Keď spustíme program, mali by sme obdržať nasledujúci výpis:

ORACLE ERROR:12162  - ORA-12162: TNS:net service name is incorrectly specified

Tejto chyby sa neľakajte. Zaviedol som ju do kódu schválne aby som vám ukázal ako na chyby vyvolané OCCI. Ak sa vyskytne akákoľvek chyba, OCCI vyvolá výnimku SQLException. Ta v sebe nesie informácie ako číslo chyby a text chyby. V catch() bloku môžete vidieť funkcie getErrorCode() a getMessage() pomocou ktorých sa dopracujeme k textu a číslu chyby.

Chybu odstránime špecifikovaním DB. Lenže čo tam napísať? Ak ste sa niekedy pokúšali pripojiť na MySQL pomocou API, tak viete že na vytvorenie spojenia potrebujete IP alebo DNS meno servera a port na ktorom počúva databáza. Tu sa nič také nenachádza. Oracle ma vyvinutý vlastný sieťový protokol TNS(Transparent Network Substrate) pomocou ktorého je riešená komunikácia klient-server. Súčasťou tohto protokolu je aj TNS meno. Je to meno databázy ktoré presne špecifikuje kde databáza je, na ktorom porte počúva. Toto meno je definovane v súbore ktorý nájdeme v ORACLE_HOME/network/admin/tnsnames.ora. V tomto súbore sa nachádza zoznam všetkých databáz ku ktorým sa z nášho systému môžeme pripojiť. Pravdepodobne tam budete mať len jeden záznam a to s menom XE. Presne tak sa volá naša databáza a presne tento názov potrebujeme. Takže si upravte riadok kódu na nasledujúci:

main.cpp

#define USER  "SYSTEM"
#define PASS  "****"
#define DB    "XE"

Program už nebude vyhadzovať žiadnu výnimku a mal by skončiť bez chyby.

Pooling

Pravdepodobne nebudete vyvíjať v C/C++ len klientsku aplikáciu z jedným spojením. Skôr budete OCCI použivať v rôznych midlleware aplikáciach. Tieto aplikácie sú charakteristické tým, že sa skladajú z väčšieho množstva vlákien, spojení. Pri takých aplikáciach si poviete: čo vlákno, to spojenie. To je však čo sa týka performance trošku nešťastné riešenie. Totižto vlákna vznikajú, zanikajú. Takisto budu vznikať a zanikať aj spojenia. Načo však by malo niečo zanikať, keď to môžeme použiť pri niečom vznikajúcom? OCCI obsahuje jednu špecialnú triedu ktorá je ako šitá na situácie kedy pracujeme z viacerými spojeniami. Volá sa ConnectionPool. Táto trieda sa vkladá medzi Enviroment a Connection. Jej úlohou je kompletný a čo najefektívnejší manažment viacerých spojení.

main.cpp

#include <iostream>
#include <occi.h>

using namespace std;
using namespace oracle::occi;

#define USER  "SYSTEM"
#define PASS  "****"
#define TNS   "XE"

int main()
{
   Environment*    env;
   ConnectionPool* conpool;
   Connection*     con1;
   Connection*     con2;

   try {
      env     = Environment::createEnvironment();
      conpool = env->createConnectionPool(USER, PASS, TNS, 0, 1, 1);

      //vytvorenie a ukoncenie spojenia con1
      cout << "open connections:" << conpool->getOpenConnections();
      con1 = conpool->createConnection(USER, PASS);
      cout << "open connections:" << conpool->getOpenConnections();
      conpool->terminateConnection(con1);

      //vytvorenie a ukoncenie spojenia con2
      cout << "open connections:" << conpool->getOpenConnections();
      con2 = conpool->createConnection(USER, PASS);
      cout << "open connections:" << conpool->getOpenConnections();
      conpool->terminateConnection(con2);

      env->terminateConnectionPool(conpool);
      Environment::terminateEnvironment(env);

   } catch (SQLException e) {
      cout << "ORACLE ERROR:" << e.getErrorCode() << " - " << e.getMessage() << endl;
   }

   return 0;
}

V tomto príklade sa ConnectionPool veľmi neprejaví, ale je to najjednoduchší spôsob ukážky práce s ConnectionPool. Program som okorenil pár výpismi. Tie by mali spôsobiť to, že po spustení by ste mali mať na konzole nasledujúci výpis:

open connections:0
open connections:1
open connections:1
open connections:1

Všimnite si, že Enviroment nevytvára Connection ako to bolo v predchádzajúcom príklade, ale vytvára ConnectionPool.

      ...
      conpool = env->createConnectionPool(USER, PASS, TNS, 0, 1, 1);
      ...
      env->terminateConnectionPool(conpool);
      ...

ConnectionPool má okrem klasických parametrov USER, PASS a DB ešte ďalšie 3 čísla. Prvé číslo hovorí aký bude minimálny počet otvorených spojení. Druhe číslo je číslo ktoré hovorí, aký bude maximálny počet otvorených spojení. Tretie číslo je inkrementačné číslo. Je to počet spojení ktoré sa vytvoria v prípade že bude dosiahnutý maximum spojení. O tento počet sa zvýši počet spojení. Enviroment na konci neukončuje klasické spojenie ale ukončuje pool pomocou terminateConnectionPool(). Medzi vytvorením a ukončením pool-u som vložil vytvorenie dvoch spojení v sérii aj s výpisom. Funkcia getOpenConnections() ktorú používam vo výpisoch vráti aktuálny počet otvorených spojení. Trieda Connection teraz nieje vytváraná a ukončovaná pomocou Enviromentu ale pomocou ConnectionPool-u. Meno funkcie createConnection() sa nemení, len počet parametrov je menši o TNS meno. Pooling je totižto možné použiť len vo vzťahu k jednej DB.

Vráťme sa k výpisu. Na začiatku nieje vytvorené žiadne spojenie s DB. Potom nasleduje vytvorenie spojenia con1. Po tomto kroku existuje už otvorené spojenie. Následne je spojenie ukončené, ale ConnectionPool spojenie neukončí, iba ho označí že je voľné. Stav otvorených spojení sa teda nemení. Následne sa vytvára con2. To sa však už nevytvára odznova, ale použije sa predchádzajúce spojenie, ktoré bolo označené ako voľné. Počet otvorených spojení sa opäť nemení. Nakoniec je ukončený aj con2, no opäť sa spojenie neukončuje, len sa označí za voľné. Tento mechanizmus podstatne urýchľuje vytváranie viacerých spojení v jednej aplikácii. Myslím že na dnes to bohate stačí. V ďalšom dieli si ukážeme ako vytvoriť dotaz na DB a povieme si niečo o Statementoch.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

3 názory  —  3 nové  
Hlasování bylo ukončeno    
0 hlasů

Nové články

Obrázek ke článku Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý