Tartalmi kivonat
Tartalomjegyzék Bevezetés. 3 1. A Java nyelv alapjai 1.1 A Java nyelv legfontosabb tulajdonságai. 1.11 Objektum orientált 1.12 Architektúra független és hordozható 1.13 Osztályok kezelése 1.14 Robosztus és biztonságos 1.15 Többszálúság 1.2 Java interfészek 1.3 Java appletek 1.31 Java appletek készítése 1.32 Applet beágyazása HTML forráskódba 1.33 Appletek biztonsági megszorításai 1.4 Java konvenciók. 5 5 5 6 6 7 8 9 12 12 15 15 17 2. A JDBC könyvtár 2.1 Két- és háromrétegű adatbázis-elérési modell. 2.2 JDBC meghajtók. 2.21 1-es típusú meghajtóprogramok 2.22 2-es típusú meghajtóprogramok 2.23 3-es típusú meghajtóprogramok 2.24 4-es típusú meghajtóprogramok 2.3 A JDBC csomag objektumai 2.31 JDBC interfészek 2.32 JDBC osztályok 2.33 JDBC kivételkezelő objektumok 18 19 19 19 20 20 20 21 22 22 2.4 Kapcsolódás az adatbázishoz, meghajtóprogramok használata. 2.41 Meghajtóprogramok regisztrálása 2.42 Adatbázis megnevezése,
adatbázis URL-ek 2.43 Adatbázis kapcsolat felvétele 2.5 SQL utasítások. 2.51 Statement interfész 23 23 23 25 26 28 29 Internetes adatbázis- kezelés 2.52 2.53 2.54 2.55 2.6 2.7 2.71 2.72 2.8 2.81 2.82 2.9 2.91 2.92 2.93 PreparedStatement interfész. CallableStatement interfész. Eredménytáblák kezelése, ResultSet interfész. Egy eredményhalmaz jellemzői, ResultSetMetaData interfész. Java tipusok és SQL tipusok megfeleltetése Tranzakciókezelés Tranzakciók érvényesítése és visszagörgetése. Tranzakció-izolációs szintek. SQL specifikus kivételek kezelése. Az SQLException kivételkezelő osztály. Az SQLWarning osztály A Database Metadata interfész A kapcsolat jellemzői A konkrét adatbázis jellemzői. Az adatbázis-kezelő jellemzői. 31 32 33 34 36 37 37 38 40 40 41 42 43 44 46 3. Esettanulmány 3.1 Feladat meghatározása. 3.2 Feladat elemzése. 3.21 Kapcsolatfelvétel az adatbázissal 3.22 Az SQL lekérdezés összeállítása 3.23 A
lekérdezés eredményének megjelenítése 50 51 52 52 52 53 4. Kitekintés 4.1 Internetes adatbázis-kezelés másképpen. 4.2 ASP röviden. 4.3 ADO adathozzáférési technológia. 4.4 Architektúra. 55 55 56 56 Szerver oldali adathozzáférés. Kliens oldali adathozzáférés Példa. 57 57 58 59 Irodalomjegyzék. A függelék. B függelék. 63 65 74 4.5 4.6 4.7 . 2 Internetes adatbázis- kezelés Bevezetés Ma a számítástechnika talán legdinamikusabban fejlődő területe az Internet. Nem volt olyan rég amikor még szerencsésnek érezhettük magunkat, hogy megismerkedhettünk az Internet világával de nincs már messze az az idő amikor legalább olyan természetes lesz mindannyiunknak az Internet használata mint ma a telefon. Nem csoda így hogy ez alatt a néhány év alatt az Internet technológia óriási fejlődésen ment keresztül. Ma már az Internet nem csak a szórakozás, pihenés, tanulás és ismerkedés színtere, hanem az üzleti
felhasználók is meglátták ebben a lehetőséget. A médiák nyitottak ebbe az irányba így akár rádiót hallgathatunk, televíziót nézhetünk az Interneten, ugyanakkor a reklámokkal való küzdelem lassíthatja az információtengerben való előrehaladásunkat. Egyre többször kerülünk szembe könyvesboltokkal, áruházakkal és az üzleti szféra egyéb képviselőivel miközben szokásos bolyongásunkat tesszük a Weben. Ez utóbbi azonnal felvet mindannyiunkban néhány kérdést. Korábban, amikor egy Web oldalt megtekintettünk vagy esetleg készítettünk annak megítélésében elsősorban esztétikai szempontok játszottak szerepet. Animációk jelentek meg, valamilyen Script nyelven írt kóddal dinamikussá tehettük a Web lapunkat. Itt azonban már egész másról van szó. Egy Internetes áruház már nem csupán néhány gusztusosan összeállított Web lap, hanem e mögött óriási adattartalom áll. Ilyen vagy ehhez hasonló természetű üzleti
alkalmazásokhoz komoly adatbázis-kezeléstámogatásra van szükség. Úgy tűnik, hogy míg korábban a HTML forráskódok készítése leginkább grafikusok által történt ma már egyre több olyan Web lap készül, amelyhez alapos programozói tudásra van szükség. Kevés terület fejlődött az utóbbi években a fentiekben említetthez hasonló ütemben de a Java nyelv egyike ezen keveseknek. Talán nem is függetleníthető teljesen ez a két technológia. A Java programozási nyelv születése, megjelenése a SUN-nak köszönhető. A nyelv óriási sebességgel nekilátott térhódításának. Ma még sokan várakozó állásponton vannak a Javaval kapcsolatban, hiszen hónapról hónapra újabb verziót tölthetünk le a SUN honlapjáról, bizonyos területeken még van is mit fejlődnie a nyelvnek. Egyben azonban szinte minden szoftverfejlesztéssel komolyabban foglalkozó cég egyetért: fel kell készülni a Java technológia és az Internetes alkalmazások
térhódítására. . 3 Internetes adatbázis- kezelés Az előbbiekben említett két technológia fejlődése nem függetleníthető egymástól, valószínűleg mindkettő lényeges szerepet játszott a másik fejlődésében. Ennek bizonyítéka, hogy a Java az első olyan programozási nyelv amely támogatja HTML dokumentumokba szúrható programok (ún. programkák, appletek) készítését A másik oldalról pedig a Java appletek segítségével egy Web lap már szinte tetszőleges funkcionalitással felruházható. Ezen szakdolgozat célja az hogy részletesen bemutasson egy technológiát Internetes alkalmazások fejlesztésére. A fentiek alapján nem meglepetés hogy a Java nyelv ilyen irányú lehetőségei kerülnek bemutatásra. Még ezen a ponton érdemes leszögezni, hogy ma még nem biztos, hogy ez az a technológia, amely a legalkalmasabb ilyen alkalmazások fejlesztésére, de a nyelv fejlődése miatt mindenképpen érdemes ezt áttekinteni. Hogy teljes
legyen a kép és a tartalom megfeleljen a cím által felvetett elvárásoknak nem maradhatott ki a dolgozatból hogy a Java mellett bemutatásra kerüljön egy alternatív lehetőség. Az egyéb lehetséges megoldások közül az ASP és ADO fogalmak köré épülő technológiát mutatom be nagyvonalakban. Hasznos lehet ennek a szakdolgozatnak az áttekintése azok számára, akik valamilyen Internetes alkalmazás készítésére adták a fejüket de nem tudják, hogy milyen irányba induljanak illetve azoknak, akik ismerkednek a Java nyelv lehetőségeivel. . 4 Internetes adatbázis- kezelés 1. A Java nyelv alapjai A szakdolgozat keretén belül nem a Java nyelv bemutatása a cél. Ennek ellenére azonban elkerülhetetlen a nyelv néhány jellemző tulajdonságának, nyelvi eszközeinek, filozófiájának áttekintése. 1.1 A Java nyelv legfontosabb tulajdonságai A nyelv szintaktikai illetve szemantikai szempontból a C, C++ vonal követője. A Java sok mindenben
hasonlít a C++ -hoz de jelentősen egyszerűbb (bár ez megítélés kérdése) annál. Köszönhető ez többek között annak is hogy a Java egyáltalán nem használ mutatókat, nem engedi az operátorok felüldefiniálását, és nincs lehetőség többszörös öröklődésre. Ez utóbbi hiánya azonban nem okoz problémát ennek kiváltására szolgálnak a Java interfészek. Ezek nagy jelentőséggel bírnak a szakdolgozat szempontjából is, így később bővebben visszatérek rájuk. 1.11 Objektum-orientált A Java a C++ objektum orientált tulajdonságait tartalmazza. Osztályokat a class kulcsszó segítségével hozhatunk létre. Az osztályok tagfüggvényekből (metódus) és tagváltozókból állnak. Egy fontos különbség a Java és a C++ között hogy a Java minden metódusa virtuális műveletként viselkedik, ezt a C++ -tól eltérően nem kell külön jelölni. A metódusok, tagváltozók láthatóságának minősítése a private, protected, public
kulcsszavakkal tehető meg. Az elkészített osztályainkat egy hatékony csomagkezelő mechanizmusnak köszönhetően csomagokba rendezhetjük. Erre a package kulcsszó szolgál. Ennek szerepe van a láthatóságra is Az azonos csomagban levő objektumok a C++ -ban megszokott friend kapcsolatban állnak egymással. Az öröklődés megvalósítása az extends kulcsszóval történik, és hasonló elveken működik mint a C++ -nál. Az öröklődés tekintetében a Java és a C++ között az a jelentős . 5 Internetes adatbázis- kezelés különbség hogy a Javaban nincs lehetőségünk többszörös öröklődésre. Ehelyett a Javaban interfészeket (interface) készíthetünk és ezeket különböző osztályokban implementálva a többszörös öröklődéshez hasonló eredményre juthatunk. 1.12 Architektúra független és hordozható Napjainkban egyre fontosabb hogy az általunk készített alkalmazás ne csak a titkárnő PC-jén hanem a főnök SUN gépén is fusson
és ugyanazokat a műveleteket végezze el. Az első programozási nyelv a Java amely erre a kérdésre kielégítő választ ad. A Java nem tartalmaz architektúra vagy implementációfüggő elemeket. Erre egy jó példa, hogy a Java beépített típusai nyelvi szinten meghatározottak, azaz a típus tárolásához szükséges memóriaterület a típus értelmezési tartománya rögzített, minden platformon egyező. Természetesen ennek megvannak a hátrányai is hiszen az egyes platformokon nem éppen ezek az optimális paraméterek de a platformfüggetlenségnek meg van az ára. Az hogy a Java programok architektúra függetlenek egy új filozófiának köszönhetők. A programunkat egy köztes kódra kell lefordítanunk, amely platformtól független kód. Ezt a köztes kódot (byte kód) adjuk át egy értelmezőnek a JVM (Java Virtual Machine) –nek. Ez a JVM már platformonként más és más és ez a JVM a platformtól függően értelmezi és végrehajtja a byte kód
szerint a műveleteket. Ez a gyakorlatban azt jelenti hogy bármilyen platformon is dolgozunk az elkészített programunkat erre az általános köztes kódra fordítjuk le és ezt a köztes kódot aztán tetszőleges platformon (ami tartalmazza a saját JVM-jét) futtathatjuk. 1.13 Osztályok kezelése A Java nyelv fejlesztőkészlete rengeteg hasznos előre elkészített csomagot biztosít számunkra a hatékony munkához. Ezek használata azonban eltér az eddigiekben esetleg . 6 Internetes adatbázis- kezelés megszokottaktól. A C-ben megszokott include-nak látszólag megvan a megfelelője a Java-ban ennek azonban ténylegesen csak látszólag ugyanaz a működése. Amikor az import kulcsszó segítségével megjelöljük azokat az osztályokat, csomagokat, interfészeket, amiket használni akarunk az nem azt jelenti hogy fordításkor azok bemásolódnak a byte-kódba hanem csak egy hivatkozást helyezünk el ennek segítségével. A Java osztálybetöltési
mechanizmusa szerint ezek az osztályok futási időben kerülnek betöltésre, egy osztály az osztály betöltő (class-loader) által akkor kerül betöltésre, amikor szükség van rá. Az osztály betöltő képes az adott osztályt akár másik gépről is betölteni. Ha az Interneten egy olyan oldalt találunk, amelyben egy Java applet található és a számítógépünkön telepítve van a megfelelő JVM akkor az osztály betöltő letölti a megfelelő szerver gépről az applethez tartozó osztályt majd futtatja azt. Az applet által használt osztályokat hasonlóképpen tölti be de csak akkor amikor szükség van rájuk. Fontos tudni még hogy egy ilyen esetben az osztálybetöltő először mindig a kliens gépen nézi meg hogy megtalálható-e a megfelelő osztály majd ha itt nem találja akkor fordul ahhoz a szerver géphez ahonnan az applet maga letöltődött. Így egy osztály fordításakor még egyáltalán nem tudhatjuk, hogy adott esetben milyen osztályt fog
éppen betölteni az osztálybetöltő. Itt persze ismét meg kell említeni, hogy ennek a technológiának a rugalmassága gyakran a hatékonyság rovására megy. Nem beszélve arról hogy könnyen megtréfálhat minket az osztálybetöltő amikor nem értjük hogy miért nem úgy működik ahogyan azt mi elképzeltük és rájövünk hogy nem is azt az osztályt tölti be amit mi gondolunk. 1.14 Robosztus és biztonságos A robosztusság egyik fontos alapja a nyelv típusossága. Nincsenek automatikus konverziók. A nyelv hatékony hibakezelő (exception) eszközzel van ellátva A mutatók kiküszöbölése pedig rengeteg hibalehetőségtől való megszabadulást jelent. Nagyon kényelmes és hatékony ezek mellett a Java szemétgyűjtögetési mechanizmusa (gerbage collection) is. A biztonságosság egyik alapköve az osztálybetöltő. A korábbiakban már láthattuk hogy az osztálybetöltő elsősorban a helyi gépről tölti be az osztályokat ha az lehetséges. . 7
Internetes adatbázis- kezelés Amennyiben nem akkor a betöltő és a JVM által további ellenőrzéseken mennek keresztül ezek az osztályok mielőtt a JVM futtatná őket. Az appletekre további biztonsági rendszabályok is vonatkoznak, hiszen ezeket esetenként akaratunktól függetlenül is futtathatjuk. Ezekre a biztonsági megszorításokra a későbbiekben bővebben kitérünk. 1.15 Többszálúság A Java nyelv platformfüggetlensége miatt ugyanúgy alkalmas PC környezetre illetve nagygépes többprocesszoros környezetre való fejlesztésre. Így nem meglepő hogy ebben a nyelvben nagyobb szerepet kap a párhuzamos programozás lehetősége. A Javaban két lehetőségünk van párhuzamosan futtatható szálak létrehozására. Az első a java.langThread osztály kiterjesztése Ezzel létrehozunk egy leszármazott osztályt amelynek run metódusának átírásával azt a számunkra megfelelő funkcionalitással láthatjuk el. Ennek az osztálynak a start metódusával
indíthatjuk el a szálat A másik lehetőség szálak létrehozására a Runnable interfész amelyet egy tetszőleges osztályban implementálva egy szálat hozhatunk létre. A Runnable interfész egyetlen metódust a run metódust definiálja, és nekünk ezt kell implementálnunk. Ennek előnye az előzővel szemben, hogy tetszőleges osztályt elindíthatunk szálként (így pl. appletet is), hátránya viszont hogy míg az első esetben a Thread osztályból való öröklődésnél további metódusokat is örököltetünk, a második esetben csak a run metódus szolgálja a szálat. A Java szálak a Hoare-féle monitor koncepciót használják a kritikus részek szinkronizálására. Minden Java objektumhoz kapcsolódik egy monitor, nekünk annyi a dolgunk hogy meghatározzuk, hol akarunk monitort használni. A syncronized kulcsszó segítségével osztályokhoz, metódusokhoz illetve változókhoz rendelhetünk monitort. . 8 Internetes adatbázis- kezelés 1.2 Java
interfészek Korábban kiderült hogy a Java nem teszi lehetővé a többszörös öröklődést, de ennek ellenére ad lehetőséget ennek elkerülésére, vagyis más módon történő megvalósítására. Ezt a nyelvi eszközt azért emelem ki a többi közül, mert a későbbiekben ennek komolyabb jelentősége lesz hiszen a JDBC könyvtár tulajdonképpen egy interfészgyűjtemény. Az interfész fogalma nem új keletű dolog, a Java az Objective-C nyelvből vette át. Egy interfész absztrakt metódusok és konstans értékeknek a gyűjteménye. Az absztrakt metódusok olyan metódusok, amelyek csak deklarálva vannak, nincsenek implementálva. Egy osztály implementál egy interfészt, ha annak összes metódusát implementálja. Egy interfész egy olyan típusként fogható fel amelynek elemei az adott interfész implementáló osztályok. Ez azt jelenti, hogy ha egy program egy változójának típusa egy interfész, akkor annak értéke egy olyan objektum lehet, amely olyan
osztály egy objektuma ami implementálta az adott interfészt. Az interfészek között is létezik öröklődés (kiterjesztés) sőt az interfészeknél lehet többszörös öröklődést alkalmazni. Ezzel áthidalható az osztályoknál hiányolt többszörös öröklődés. Példa interfészek használatára: public interface Alakzat{ double kerulet(); double terulet(); } public interface Negyzet extends Alakzat{ double atlo(); } public interface Kor extends Alakzat{ double atmero(); } . 9 Internetes adatbázis- kezelés public interface Haromszog extends Alakzat{ double magassag(); } A fennti példában a Kor, Haromszog és a Negyzet interfész kiterjeszti az Alakzat interfészt. Ebben az esetben, ha olyan osztályt akarunk létrehozni, amely implementálja a Negyzet interfészt akkor ügyelnünk kell arra is hogy az alakzatban definiált metódusokat implementáljuk. public class Pelda1 implements Negyzet{ /* Egy olyan osztalyt definialunk amely implementalja a Negyzet
interfeszt */ double oldal; /* Konstruktor / public Pelda1(double a){ oldal = a; } /* A konstruktor a Javaban is az objektum inicializalasara valo / /* Metodusok implementalasa / public double atlo(){ return Math.sqrt(oldal*oldal+oldaloldal); } public double terulet(){ return oldal*oldal; } public double kerulet(){ return 4*oldal; } } . 10 Internetes adatbázis- kezelés Példa a többszörös öröklődésre: public interface Haz extends Haromszog,Negyzet{ boolean vanKemeny(); } Amennyiben ezt az interfészt implementáljuk egy osztályban akkor az olyan, mintha egy többszörös öröklődést hajtottunk volna végre. public class Pelda2 implements Haz{ double kemeny; double alap; double teto; /*Konstruktor/ public Pelda2(double al,double te,double ke){ alap = al; teto = te; kemeny = ke; } /*Metodusok implementalasa/ boolean vanKemeny(){ if (kemeny == -1) return false; else return true; } double atlo(){ return Math.sqrt(oldal*oldal+oldaloldal); } . 11 Internetes
adatbázis- kezelés double magassag(){ return Math.sqrt(teto*teto-alapalap/4); } double kerulet(){ return 3*alap+2teto; } double terulet(){ return alap*alap+alapmagassag()/2; } } 1.3 Java appletek A Java az első olyan programozási nyelv, amely lehetővé teszi, hogy ablakszerű objektumot szúrhassunk be egy HTML forráskódba. Ezen appletek úgy kezelhetők, mint egy form amelyen különböző objektumokat (textbox, choice, listbox, stb) helyezhetünk el. Így a Java appletek alkalmasak interaktív Internet/Intranet alkalmazások készítésére is 1.31 Java appletek készítése Ha egy appletet akarunk készíteni, akkor egy osztályt kell származtatnunk a java.appletApplet osztályból Ekkor kapunk egy appletet amelyet úgy alakíthatunk saját szájízünk szerint hogy felülírjuk a java.appletApplet osztály metódusait vagy új metódusokat adunk hozzá. Így pl a paint metódus segítségével beállíthatunk az appletnek háttérképet, a böngészőbe új URL-t
tölthetünk be, a showStatus(String) metódus segítségével üzeneteket küldhetünk a felhasználónak a böngésző státuszsorán keresztül. . 12 Internetes adatbázis- kezelés Egy applet a háttérben zenét játszhat le, kommunikálhat az adott HTML oldalon és csak az azon az oldalon található másik applettel. Tulajdonképpen majdnem mindent megtehetünk egy applet segítségével, amit eddig az alkalmazásaink formjaival megtehettünk, így kapcsolódhatunk adatbázishoz a Java JDBC csomagjának közreműködésével, lekérdezéseket futtathatunk, sőt update műveleteket is elvégezhetünk ha van ehhez jogosultságunk az adott adatbázisban. Példa: Az alábbi példa applet egy gombot és egy szöveges mezőt rak ki és ha a felhasználó megnyomja a gombot akkor egy üdvözlőszöveget ír a szövegmezőbe. Az üdvözlőszöveg lehet egy a HTML forrásban megadott paraméter (lásd később) vagy ha ott nem adjuk meg akkor egy előre megadott szöveg. Az init()
metódus inicializálja az appletet. Az applet implementálja az ActionListener interfészt ami az eseménykezelés – megnyomjuk a gombot - szempontjából érdekes. Ennek az interfésznek a metódusa az actionPerformed melyet implementálva elvégezzük a szövegmező kitöltését. import java.awt*; import java.awtevent*; import java.applet*; /* Az osztalybetoltonek szolo eleresi ut megadas / public class Pelda3 extends Applet implements ActionListener { String udvozlet = ”Hello, World!”; Button kiir button; TextField szovegDoboz = new TextField(); . 13 Internetes adatbázis- kezelés public void init(){ kiir button = new Button(”Kiir”); kiir button.addActionListener(this); add(kiir button); szovegDoboz = new TextField(); add(szovegDoboz); setLayout(new BorderLayout()); if (param = getParameter(”udvozloSzoveg”)!=null) udvozlet = param; } public void actionPerformed(ActionEvent e){ if (e.getSource == kiir button) szovegDoboz.setText(udvozlet); } } . 14
Internetes adatbázis- kezelés 1.32 Applet beágyazása HTML forráskódba Egy applet beszúrása a HTML szabvány szerint történhet. A forráskódba egy applet taget kell elhelyeznünk melyben meg kell adnunnk az appletet meghatározó osztályt, az applet méreteit, és ha vannak olyan archív osztálycsomagok (jar,zip,cab) amiket az applet használ akkor azok elérési útját. Az applet paramétereit külön param tag-ekben adhatjuk meg. A fennti appletet a következőképpen szúrhatjuk be egy HTML forráskódba: <HTML><HEAD> <TITLE>Első applet</TITLE> </HEAD> <BODY> <APPLET code=Pelda3.class ARCHIVE= height=200 width=40> <PARAM name=”udvozloSzoveg” value=”Első applet!”> </APPLET> </BODY> </HTML> 1.33 Appletek biztonsági megszorításai Az appletekből használt JDBC esete jóval bonyolultabb az alkalmazásokénál. Az alkalmazásokkal ellentétben az appleteknél figyelembe kell vennünk
bizonyos biztonsági megszorításokat. Ennek az az oka hogy amikor egy applet letöltődik a kliensre, a kliensen fut és ott végez műveleteket. Mivel nem tudhatjuk előre hogy az az applet milyen műveleteket végez ezért joggal lehetünk bizalmatlanok velük szemben. . 15 Internetes adatbázis- kezelés A Java nyelv tervezői felismerték ezt a problémát, és ennek megoldására vezették be a biztonsági megszorításokat: - - - - Az appletek nem férhetnek hozzá az őket letöltő kliens fájlrendszeréhez, azaz nem olvashatnak, kereshetnek, módosíthatnak azon fájlokat, nem hozhatnak létre könyvtárakat. A letöltött appletek nem kommunikálhatnak a hálózaton csak azzal a géppel ahonnan letöltöttük őket. Ez azt jelenti, hogy nem hozhat létre hálózati összeköttetést a hálózat további gépeivel, nem vehet részt többrésztvevős multicast kommunikációban Az AWT felhasználói felület egyes elemeit nem használhatjuk az appletekben, pl. nem
használhatunk menüket, új ablak létrehozásakor a felhasználó mindig figyelmeztető üzenetet kap. Az appletek nem hozhatnak létre új végrehajtási szálakat, a saját szálcsoportjukat kivéve egyéb szálakat el sem érhetnek. Az appletek osztályelérési lehetőségei bizonyos csomagoknál korlátozottak esetleg tiltottak. A JDBC adatbázis-kapcsolat szempontjából a következő dolgokat kell figyelembe vennünk: egy applet csak azon a szerveren lévő adatbázishoz kapcsolódhat, ahonnan letöltődött, sőt ha a meghajtót is a hálózatról töltötték le, akkor ez is csak a forrásgépen található adatbázisok elérésére használható. Ha appletekből akarunk interneten keresztül adatbázisokat elérni, akkor ügyelnünk kell a Driver megfelelő kiválasztására. A Driverek típusainál, ahogy azt a későbbiekben tárgyalni fogjuk az 1. és 2 típusú driverek nem megfelelőek ilyen adatbázis-kapcsolat létrehozására, hiszen ezek a kliensen lévő bináris
programok felhasználását igénylik. Az appletek biztonsági megszorításai természetesen különböző módszerekkel részben vagy akár teljesen megkerülhetők. A Web Browserek nagy része ad erre lehetőséget, de a Java 1.1 megjelenése óta erre más lehetőségünk is van A Java 11 lehetőséget nyújt az appletek digitális aláírására, valamint hogy bizonyos megbízható forrásból származó appletek mentesüljenek részben vagy akár egészében ezen biztonsági megszorítások alól. A Java osztálybetöltési mechanizmusának következtében van egy más lehetőségünk is arra hogy ezeket a megszorításokat elkerüljük, ugyanis elegendő ha az applet osztályát ’installáljuk’ a klienseken akkor a betöltéskor az nem a szerverről fog letöltődni, hanem a . 16 Internetes adatbázis- kezelés kliensről így ennek az appletnek a szempontjából már a kliens lokális környezetnek számít. Megjegyzendő, hogy a JDBC nem foglalkozik az
ügyfélprogram és az adatbázis-kezelő közötti adatátvitel titkosításával, ez a meghajtó feladata, felelőssége. 1.4 Java konvenciók Egy Java osztály készítése közben érdemes a következőket betartanunk: - Egy osztály illetve interfész neve mindig nagybetűvel kezdődik. Pl public class Applet Az osztályok metódusainak neve mindig kisbetűvel kezdődik Pl. public void init() Azokban a nevekben, amelyek összetett szavaknak felelnek meg a tagokat kezdjük nagy betűvel. Pl addActionListener() A Java azon metódusai, amelyek logikai értéket adnak vissza általában az angolból az is szócskával kezdődbnek. Pl public boolean isEmpty() Azok a metódusok, amelyek valamilyen érték beállítására szolgálnak a ”set” míg azok amelyek egy érték lekérdezésére szolgálnak a ”get” szócskával kezdődnek. Általában ez a két forma együtt található meg így amennyiben a későbbiekben egy osztály egy set-tel kezdődő metódusáról van szó,
annak megvan a get-tel kezdődő megfelelője is még ha az nem is kerül említésre. Pl setLayout(), getLayout() . 17 Internetes adatbázis- kezelés 2. A JDBC könyvtár A JDBC (Java DataBase Connectivity) a JDK 1.1 verziójában megjelent csomag amely az adatbázis-kezeléssel kapcsolatos problémák megoldására szolgál. A könyvtár lényege, az ún. JDBC menedzser tulajdonképpen két felületet specifikál Felsô felülete az a programozói interfész, amelynek révén a programozók elérhetik az adatbázis szolgáltatásait. Ez a csomag (java.sql*) tulajdonképpen egy interfész gyűjtemény (az interfészek mellett néhány osztályt és hibakezelő objektumot is tartalmaz a JDBC csomag) amelyben minden adatbázis művelethez kapcsolódik egy interfész (pl. Driver, Connection, stb) A menedzser alsó szintje viszont a különböző adatbázisok elérését megvalósító meghajtó programok implementációjánál játszik szerepet. Így a JDBC szolgáltatásait
akkor tudjuk igazán kihasználni, ha ezeket az interfészeket az adott adatbázis-kezelő felé implementáljuk. Szerencsére ezt nem nagyon kell megtennünk mert a legtöbb adatbázis-kezelőhöz találunk vagy vásárolhatunk ilyen kész implementált JDBC csomagokat. Így pl ha egy Oracle adatbázist akarunk kezelni a JDBC csomag eszközeivel akkor az Oracle által elkészített ingyenesen az Internetről letöltött JDBC csomag használható. Így az implementációs felületet az interfészek eltakarják, ha van megfelelő meghajtóprogramunk akkor a hogyannal nem kell foglalkoznunk. A JDBC-t az adatbázis-elérés alacsony szintû, közvetlenül az SQL utasítások szintjét használó könyvtárának szánták. A JDBC teljesen Jávában implementálódott, így az implementáció megôrizte a Jáva kód architektúra-függetlenségét, hordozhatóságát. . 18 Internetes adatbázis- kezelés 2.1 Két- és háromrétegű adatbáziselérési modell A JDBC az adatbázis
eléréshez alapvetően kétféle lehetőséget nyújt. • Kétrétegű elérés: A program közvetlenül az adatbázis-kezelő rendszerrel kommunikál. Az adatbázis illetve a program akár különböző gépeken is lehet • Háromrétegű elérés: A program egy közbülső réteggel kommunikál közvetlenül. Ez a réteg értelmezi a parancsokat és továbbítja azt az adatbázis-kezelő rendszer felé. Az adatbázis lekérdezések eredmény szintén ezen rétegen át juthatnak el a program felé. Ez a szolgáltató réteg lehet, de nem feltétlenül Java-ban van implementálva. A középső réteg optimalizálási és ellenőrzési feladatokat is ellát. 2.2 JDBC meghajtók A JDBC meghajtóprogramok egy fizikai kapcsolatot nyújtanak a JDBC hívások és az adatbázis-kezelő rendszerek között. Biztosítják a JDBC hívások értelmezését és végrehajtását. Jelenleg a hozzáférhető JDBC meghajtóprogramok négy tipusát különböztetjük meg: 2.21 1. tipusú
meghajtóprogramok: JDBC-ODBC áthidaló program. Már létező ODBC meghajtóprogramok használatát teszik lehetővé. A Java-ból közvetlenül is használni lehet ODBC hívásokat, de ajánlott ezen áthidaló programok használata, amellyel biztosíthatjuk a platformfüggetlenséget, illetve használhatjuk a JDBC –interfész objektumorientált lehetőségeit. . 19 Internetes adatbázis- kezelés 2.22 2. tipusú meghajtóprogramok: JDBC-saját API áthidaló programok. Ezen meghajtóprogramok a JDBC hívásokat közvetlenül alakítják át az adott adatbázis API hívásaira. Hátránya: - Minden kliens gépen installálni kell az adott adatbázis API-t megvalósító programnak. - Adott meghajtóprogram csak az adott adatbázishoz használható. 2.23 3. tipusú meghajtóprogramok: A háromrétegű adatbázis-elérési modellt valósítják meg. A meghajtóprogram a JDBC hívásokat adatbázis-független hálózati-protokoll hívásokká alakítja át. Ezeket egy
szerverprogram értelmezi és átalakítja az adott adatbázis API hívásaivá. Ez a szerverprogram tart fenn közvetlen kapcsolatot az adatbázissal. 2.24 4.tipusú meghajtóprogramok: JDBC-saját protokoll Java meghajtóprogram. Tisztán Java-ban írt meghajtóprogramok Kétrétegű adatbázis-elérést valósítanak meg. A JDBC hívásokat közvetlenül a megfelelő adatbázis-kezelő hívásaivá alakítják át. Ezek általában szintén csak egy adott adatbázis-kezelő esetében használhatóak. Meghajtóprogramok választásakor figyelembe kell vennünk a Java biztonsági kérdéseit. Így az 1.illetve 2 típusú meghajtóprogramokat appletekből nem használhatjuk, hiszen azok bináris programok használatát igénylik a klienseken. A 3 illetve 4 típusú meghajtóprogramok tisztán Javaban íródtak így ezek használhatóak. A 4 típusú meghajtóprogramok további előnye, hogy a kliensen nem igényelnek installálást. A további tervek egy olyan irányba mutatnak
melyben a JDK részeként tartalmazni fog olyan 3. típusú meghajtóprogramot amelyet adatbázis-kezelőtől függetlenül használhatunk. . 20 Internetes adatbázis- kezelés 2.3 A JDBC csomag objektumai A JDBC csomag elsősorban interfészek gyűjteménye, de tartalmaz néhány osztályt amelyben kivételkezelő objektumok is vannak. 2.31 JDBC interfészek A JDBC csomagban a következő interfészek találhatóak: - CallableStatement Connection DatabaseMetaData Driver PreparedStatement ResultSet ResultSetMetaData Statement A Driver interfész az adatbázis-meghajtó paramétereinek megadására szolgál. A Connection interfész szolgál az adatbázis-kapcsolat paramétereinek beállítására. Itt adhatjuk meg magának az adatbázisnak az elérhetőségét, felhasználói nevet, jelszót illetve egyéb paramétereket. A Statement, CallableStatement, PreparedStatement interfészek SQL parancsok futtatására használhatóak. A ResultSet interfész segítségével lehet
lekezelni az SQL lekérdezések eredményhalmazát, míg ennek az eredményhalmaznak a tulajdonságait (pl. oszlopok típusa) a ResultSetMetaData interfész segítségével tudhatjuk meg. A DatabaseMetaData interfész segítségével lekérdezhetjük magának az adatbázisnak a tulajdonságait (pl. milyen táblák vannak benne, ezekben a táblákban milyen mezők vannak,). . 21 Internetes adatbázis- kezelés 2.32 - JDBC osztályok Date DriverManager DriverPropertyInfo Time TimeStamp Types A Date egy JDBC dátum osztály, amely java.utilDate osztályból van származtatva Szintén ebből az osztályból van származtatva a Time és a TimeStamp amelyek a JDBC idő és időbélyeg kezelő osztályai. A DriverManager tartja nyilván a JDBC meghajtóprogramokat. A DriverManager segítségével egyszerre több meghajtóprogramot is nyilvántarthatunk, így egy adott esetben a DriverManager válogathat is a megfelelő meghajtóprogramok között. Az aktuális meghajtónk
jellemzőire a DriverPropertyInfo osztály segítségével kérdezhetünk rá. A Types osztály a szabványos SQL típusokat azonosító konstansokat tartalmazza. (pl. CHAR,VARCHAR,INTEGER, ) 2.33 - JDBC kivételkezelő objektumok DataTruncation SQLException SQLWarning Az SQLException az adatbázishibákat, míg az SQLWarning a figyelmeztetéseket leíró osztályok. A DataTruncation egy az SQLWarning osztályból származtatott osztály amely egy adat értékének olvasás/írás esetén történő csonkítása esetén figyelmeztet. . 22 Internetes adatbázis- kezelés 2.4 Kapcsolódás az adatbázishoz, meghajtóprogramok használata A JDBC lehetőségeinek használatához alkalmazásainkba illetve appletekbe importálnunk kell a JDBC csomag osztályait, amelyek a java.sql csomagban találhatók import java.sql*; 2.41 Meghajtóprogramok regisztrálása - a Driver interfész és a DriverManager osztály A meghajtóprogramok implementálják a java.sqlDriver interfészt
Ez az interfész néhány metódusa információval szolgál magáról a meghajtóprogramról, így a getMajorVersion() és a getMinorVersion(), amelyek verziószámok megadására szolgálnak. A Driver-nek természetesen meg kell felelni a JDBC előírásoknak, a Driver interfész tartalmaz egy olyan metódust ami megadja hogy a meghajtóprogram megfelel-e ezeknek az előírásoknak – ez a jdbcCompilant() metódus. A későbbiekben bővebben is lesz róla szó, most csak megemlítem hogy az adatbázishoz való kapcsolódás ennek az interfésznek a connect(String url, Properties prop) metódusával történik amelynek paraméterként egy – szintén a későbbiekben bővebben tárgyalásra kerülő – adatbázis URL-t kell paraméterként átadni. Ez az URL tulajdonképpen a kapcsolat paramétereinek egy részét tartalmazza. A további paraméterek egy másik argumentumban adhatók át Egy adatbázis url összeállítása előtt a Driver interfész getPropertyInfo(String url)
metódusával megtudhatjuk, hogy az adott kapcsolathoz az url-ben milyen paramétereket kell megadnunk. Ezt általában a meghajtókhoz mellékelt leírásokból is megtudhatjuk Miután összeállítottuk az adatbázis URL-t, mielőtt létrehoznánk a kapcsolatot tesztelhetjük azt hogy a meghajtóprogramnak és az adatbázisnak megfelelően állítottuk-e össze. Ezt a Driver interfész acceptsURL(String url) metódusával tehetjük meg Ezzel tulajdonképpen megismertük ennek az interfésznek az összes metódusát. A továbbiakban tárgyalásra kerülő interfészek is hasonló filozófia szerint épülnek fel, nagyrészük jóval több metódust tartalmaz. Ezek a metódusok megtalálhatók a Java . 23 Internetes adatbázis- kezelés könyvek referencia oldalain vagy letölthetők a SUN Web oldalairól a JDBC API teljes leírásában. Így nem törekszem arra hogy ezentúl az összes metódus szintaktikájára és funkciójára kitérjek ezért főleg csak a legfontosabb
metódusokról lesz szó gyakorlati példákon keresztül bemutatva. Alkalmazásainkban egyszerre több meghajtóprogramot is használhatunk. Az éppen használni kívánt meghajtóprogram kiválasztása történhet annak közvetlen megnevezésével, vagy a DriverManager osztály használatával. A DriverManager osztály nyilvántartja az éppen használható (nyilvántartásba vett) meghajtóprogramokat és az adott adatbázis-kezelővel való kapcsolat felvételekor kiválasztja a megfelelő meghajtóprogramot és aktivizálja azt. Emellett a hibaüzenetek nyomkövetéséért is ez az osztály a felelős. Egy új meghajtóprogramot az osztály registerDriver() metódusával lehet regisztrálni. A meghajtóprogramok közvetlen megnevezése és betöltése a Class.forName() metódussal lehet. A jdbc.drivers rendszerparaméter a meghajtóprogramok neveinek kettőspontokkal elválasztott listáját tartalmazza, amelyet a DriverManager osztály inicializálásakor automatikusan betölt. A
DriverManager osztály segítségével megadhatunk naplófájlt setLogStream(PrintStream out), illetve beállíthatjuk, hogy mennyit várakozzon a meghajtóprogram a kapcsolódásra setLoginTimeout(int sec). Példa: Új meghajtóprogram regisztrálása: Class.forName(”jdbcodbcjdbcodbcDriver”); Class.forName(”comsybasejdbcSybDriver”); Az előbbi egy jdbc-odbc áthidaló (1-es típusú), míg az utóbbi egy elsősorban Sybase adatbázis-kezelőkhöz használható (4-es típusú) meghajtó. Itt érdemes megemlíteni, hogy a Java csomaghierarchiája bizonyos tekintetben megfeleltethető egy könyvtár-hierarchiának, azaz a fenti példa szerint a Sybase Drivere . 24 Internetes adatbázis- kezelés mögött egy JAVA HOMEcomsybasejdbcSybDriver.class osztály kell legyen Ahhoz hogy a regisztrálás sikeres legyen ennek a könyvtárstruktúrának megfelelőnek kell lenni. 2.42 Adatbázis megnevezése, adatbázis URL-ek A fenntiek szerint regisztrált adatbázis-meghajtónkat
ezután már szabadon használhatjuk a programunkban. Mielőtt kapcsolatot akarnánk kiépíteni az adatbázis-kezelővel még egy-két dolgot tisztáznunk kell. A kapcsolatot csak megfelelően meghatározott adatbáziskezelővel, annak adott adatbázisával és a bejelentkezésre feljogosító felhasználói névvel és jelszóval tehetjük meg. Ezen paraméterek megadására a JDBC ún adatbázis URL-eket használ. Egy URL a hálózati erőforrások azonosítására szolgál. Az adatbázis-URL az elérni kívánt adatbázist jelöli ki. Szintaxisa: jdbc:<alprotokoll>:<adatbázis-hivatkozás> Ahol - jdbc: a protokoll neve - az alprotokoll nevét a meghajtóprogram gyártója határozza meg - a harmadik tag pedig az elérni kívánt adatbázisra vonatkozó további adatokat tartalmaz. Így az adatbázis nevét, kommunikáció port számát Ennek a szintaxisa meghajtóprogramtól függő. Példák: jdbc:odbc:SQL Anywhere 5.0 Sample;UID=dba;PWD=sql
jdbc:sybase:Tds:localhost:7373 Előbbi egy ODBC meghajtóprogram használatát teszi lehetővé. A harmadik tagban kell megadnunk a tulajdonképpeni ODBC adatforrás nevét, ami itt egy SQL Anywhere . 25 Internetes adatbázis- kezelés adatbázis-kezelő példa adatbázisára hivatkozó adatforrás. Végül a kapcsolódás paramétereként megadjuk a felhasználói nevet és a passwordot is. Utóbbi a Sybase Inc. által gyártott jConnect 4 tipusú meghajtó szintaxisa, melyben a szervernév (itt localhost) mellett a kommunikációs port számát adjuk meg. Ami azt jelenti hogy az adott szerver adott portján várja az adott adatbázis-kezelő a kéréseket és erre a portra kapcsolódunk kéréseink végrehajtásához. 2.43 Adatbázis kapcsolat felvétele A megfelelő meghajtóprogram(ok) regisztrálása után felvehetjük a kapcsolatot az adatbázissal. Adatbáziskapcsolat felvételére két lehetőségünk van A kapcsolatot a DriverManager osztály getConnection
metódusával vesszük fel. A DriverManager osztály ekkor kiválasztja a megfelelő meghajtóprogramot és meghívja annak connect metódusát. java.sqlConnection conn = DriverManager.getConnection(”jdbc:odbc:adatforras”); Így egy Connection (interfész) objektumot kapunk. A kapcsolat lezárása a close() metódussal lehetséges. Pl. try{ Class.forName(clName); Connection con = DriverManager.getConnection ( url, uname, pwd); }catch(SQLException e){ System.outprintln("Hibaüzenet: "+etoString() ); } . 26 Internetes adatbázis- kezelés catch(ClassNotFoundException c){ System.outprintln("Hibauzenet: "+ctoString() ); } private private private private String String String String clName = "sun.jdbcodbcJdbcOdbcDriver"; url = "jdbc:odbc:SQL Anywhere 5.0 Sample"; uname = "dba"; pwd = "sql"; Az adatbázis-kapcsolat felépítésekor fel kell készülnünk az esetleges hibaeseményekre. Előfordulhat, hogy az általunk
megadott meghajtót nem találja az osztály-betöltő ezt a ClassNotFoundException kivételkezelő osztállyal kezelhetjük le, vagy egyéb kivételek – pl.rossz jelszó megadás- kezelésére az SQLException kivételkezelő használható Másik lehetőség hogy a DriverManager megkerülésével a Driver interfész connect metódusának meghívásával hozzuk létre a kapcsolatot. try{ Driver dr = (Driver)Class.forName(clName)newInstance(); java.utilProperties prop = new javautilProperties(); prop.put("user","dba"); prop.put("password","sql"); Connection con = dr.connect( url,prop); textf 1.setText( "OK" ); }catch(Exception exc){ textf 1.setText( "NemOK: "+exctoString() ); }; Ebben az esetben a connect metódus argumentumában kell megadnunk a felhasználói nevünket és a jelszavunkat. Többnyire az első megoldási módot célszerű használni. . 27 Internetes adatbázis- kezelés Egy már meg lévő
kapcsolatról illetve az adatbázis kezelőről információkat a DatabaseMetaData interfész felhasználásával kaphatunk, amelyhez az adatbázis kapcsolat getMetaData metódusának meghívásával jutunk. Ezt a későbbiekben tárgyaljuk 2.5 SQL utasítások végrehajtása – Statement, PreparedStatement, CallableStatement interfészek A JDBC adatbázis függetlenségéből következően akármilyen SQL parancs szöveges utasítás formájában átadható az adatbázisnak. Így az összes adatbázis specifikus lehetőség kihasználható a JDBC-n keresztül. Az adott adatbázis kezelő specifikus lehetőségeiről szintén a DatabaseMetaData segítségével kaphatunk információkat. Pl.: supportsOuterJoins(), supportSelectForUpdate(), supportStoredProcedures(), Ennek segítségével programjainkat adatbáziskezelőtől függetlenül írhatjuk meg. SQL utasításokat interfészeken keresztül adhatunk át az adatbáziskezelőnek. Erre három interfészt alkalmazunk: - Statement
interfész: PreparedStatement interfész: interfésznek a segítségével CallableStatement interfész: paraméterei is lehetnek egyszerű SQL utasításokat végeztethetünk vele SQL utasításokat paraméterezhetjük ennek az SQL utasításainknak nemcsak be- hanem kimenő Egy Statement interfészt megvalósító objektum a kapcsolatot jelképező Connection objektum createStatement() metódusának meghívásával hozható létre. A másik két Statement ennek megfelelő metódusa a prepareCall() illetve a prepareStatement() metódusok. A létrehozott utasításobjektumok execute(), executeQuery(), executeUpdate() metódusainak segítségével egy string paraméter formájában adhatjuk át a végrehajtandó . 28 Internetes adatbázis- kezelés parancsot az adatbázis-kezelőnek. Az executeQuery lekérdezések (SELECT), az executeUpdate módosító utasítások (DELETE, UPDATE, ), míg az execute mindkét fajta utasítás továbbítására alkalmas. 2.51 Egyszerű
Statement interfész Egy Statement objektum statikus SQL utasítások futtatására használható. Egy Statement objektum execute, executeQuery, executeUpdate metódusának meghívásával adhatjuk ki a megfelelő SQL utasításokat. execute : executeQuery : executeUpdate : többszörös SQL utasítások esetén egyszerű SQL SELECT lekérdezések esetén INSERT, UPDATE vagy DELETE utasítások esetén Példa: try{ java.sqlStatement stmt = conncreateStatement(); stmt.setQueryTimeout(20); ResultSet rs = stmt.executeQuery(”SELECT o1, o2, o3 FROM t”); while (rs.next()) { int i = rs.getInt(”o1”); // vagy rsgetInt(1) String s = rs.getString(”o2”); byte b[] = rs.getBytes(”o3”); System.outprintln(”Eredménysor = ” + i + ”, ” + s + ”, ” + b[0]); } rs.close(); stmt.close(); }catch(SQLException e){}; . 29 Internetes adatbázis- kezelés A példa egy már felépített adatbázis-kapcsolathoz hoz létre egy statement objektumot. Ezt az objektumot egy egyszerű
lekérdezés végrehajtására használja fel. A lekérdezés eredményét egy eredményhalmazban – lásd később – kaptuk meg. Ennek az eredményhalmaznak a rekordjait feldolgoztuk és kiírtuk a képernyőre. A Statement lezárására a close metódus használható. A setMaxRows(int max) metódussal beállíthatjuk, hogy az eredményhalmazunk hány sort tartalmazzon, illetve ezt le is kérdezhetjük /getMaxRows/. A további eredményekhez a getMoreResults() metódus meghívásával juthatunk hozzá. A setQueryTimeout metódussal beállíthatjuk azt az időtartamot amennyit a driver várakozzon a Statement végrehajtására, amennyiben ez alatt az idő alatt nem sikerül végrehajtani, SQLException kivétel váltódik ki. Pl.: try{ java.sqlStatement stmt = conncreateStatement(); int feldSorok = stmt.executeUpdate(”UPDATE t SET o2=’ERTEK’ WHERE o1=5”); stmt.close(); System.outprintln(feldSorok+” db rekord modositasa megtortent”); }catch(SQLException e){
System.outprintln(”Hibauzenet: ”+etoString()); }; Ebben a példában a t táblában módosítást hajtottunk végre. Ehhez hasonlóan egy táblába rekordot vihetünk (INSERT), sőt akár új táblákat vagy nézeteket is létrehozhatunk. . 30 Internetes adatbázis- kezelés 2.52 PreparedStatement interfész Egy SQL utasítás előfordítható és tárolható egy PrepareStatement objektumban. Ez hatékonyan használható SQL utasítások többszöri futtatása esetén. try{ java.sqlPreparedStatement stmt = conn.prepareStatement(”UPDATE autok SET ar=? WHERE nev=?”); stmt.setInt(1, 1000000); stmt.setString(2, ”OPEL”); int feldSorok = stmt.executeUpdate(); }catch(SQLException e){ System.outprintln(”Hibaüzenet: ”+etoString()); }; Első lépésben létrehozzuk a paraméterezhető utasítást, amelyben több paraméter is lehet. Második lépésben megadjuk a megfelelő paraméterek típusban megfelelő értékét. Majd elvégezzük az adatbázis-módosítást. A
módosítást végző metódus visszaadja a módosított sorok számát. Az objektum setXXX (setInt,setByte,setDate) metódusainak segítségével állíthatjuk be a bemenő paramétereket, itt ügyelnünk kell arra hogy az SQL típusnak megfelelő metódust hívjuk meg. SQL null érték a setNull metódussal adható meg Az aktuális paraméterek a clearParameters() metódus meghívásával törölhetőek, majd megadhatunk új paramétereket. . 31 Internetes adatbázis- kezelés 2.53 CallableStatement interfész Egy CallableStatement objektum az SQL tárolt eljárásainak meghívására használható. Egy tárolt eljárásnak lehetnek bemenő (IN) illetve kimenő (OUT) paraméterei. Egy tárolt eljárás meghívásának általános szintaxisa: {? = call procedure name[(?, ?, .)]} Ha a tárolt eljárás visszaad OUT paramétereket, akkor minden egyes OUT paraméter esetében regisztrálnunk kell ezek SQL típusait mielőtt az execute metódusok valamelyikét meghívnánk. Ez a
registerOutParameter() metódus meghívásával történik A megfelelő getXXX metódusokkal juthatunk a paraméterek értékeihez. try{ CallableStatement stmt = conn.prepareCall( "{call proc name(?, ?)}"); stmt.registerOutParameter(1, javasqlTypesTINYINT); stmt.registerOutParameter(2, javasqlTypesDECIMAL, 3); stmt.executeQuery(); byte x = stmt.getByte(1); java.mathBigDecimal n = stmtgetBigDecimal(2, 3); }catch(SQLException e){}; Megjegyzés: A TINYINT tipus megfelelője a Byte. . 32 Internetes adatbázis- kezelés 2.54 Eredménytáblák kezelése - a ResultSet interfész Vannak olyan SQL utasítások, amelyek eredményt is szolgáltatnak. Ezek az eredmények meglehetősen sokfélék lehetnek. Elképzelhető hogy az eredmény egyetlen érték de hasonlóképpen megtörténhet, hogy egy óriási eredményhalmazt produkálnak. Ezt az eredményhalmazt a felhasználó számára kezelhető formában kell tálalnunk. A JDBC csomagnak erre külön eszköze van. Az
adatbázis kezelőtől lekérdezés esetén kapott eredményhalmaz számunkra egy a java.sqlResultSet interfésznek megfelelő objektum formájában jelenik meg. Annak az osztálynak, amely ezt az interfészt implementálja implementálnia kell olyan metódusokat amelyek az adott eredményhalmaz adott rekordjának adott sorszámú mezőjének értékét meghatározza. Ilyen metódusnak minden SQL típushoz kell lennie Pl.: getBoolean(int sorszám), getByte(int s), getInt(int s), getString(int s), stb Az aktuális sor mezőinek értékét a getXXX metódusokkal kérdezhetjük le közben ügyelve a típusok megfeleltetésére. A getXXX metódusok paramétereként megadhatjuk a megfelelő oszlop nevét vagy annak sorszámát. Ha azt vizsgáljuk, hogy egy mező értéke null érték-e erről a wasNull metódus meghívásával győződhetünk meg. String s = rs.getString("FNAME"); String s = rs.getString(2); Fontos még ennek az interfésznek a next() metódusa, ennek
segítségével léphetünk az eredményhalmaz következő sorára. Amennyiben nincs következő sor ez a metódus null értéket ad eredményül. A ResultSet fenntart egy cursort amely mindig az aktuális sorra mutat. Figyelnünk kell arra, hogy amikor a Statement execute metódusainak valamelyikével egy eredményhalmazhoz jutunk, az első eredménysor elérése csak egy next metódushívás után következik be, ugyanis kezdetben ez a cursor az első sor elé mutat. Ez a cursor mindaddig érvényben marad, amíg le nem zárjuk a ResultSet vagy a Statement . 33 Internetes adatbázis- kezelés objektumot. Amennyiben szükségünk van a cursor nevére azt a getCursorName metódussal kérdezhetjük meg a ResultSet objektumtól. Erre az UPDATE vagy a DELETE SQL utasítások kiadásánál lehet szükségünk. Az oszlopok tulajdonságairól (sorszám, név, tipus, ) a ResultSetMetaData interfész segítségével kaphatunk információt a ResultSet.getMetaData() metódus meghívása
után A ResultSet objektum lezárása a close metódus meghívásával történik. 2.55 Egy eredményhalmaz jellemzői - A ResultsetMetaData interfész Ha az eredményhalmazunk pontos szerkezete ismeretlen előttünk és ez esetleg csak futási időben dől el akkor az eredményhalmaz jellemzőinek futás idejű feltérképezésére a ResultSetMetaData interfészt használhatjuk. Egy ResultSetMetaData objektumot kapunk ha meghívjuk a ResultSet objektumunk getMetaData() metódusát. Előfordulhat egy tábla teljes lekérdezésekor (select * from tabla), hogy azt sem tudjuk, hogy a táblának hány darab oszlopa van. Mivel a fentiekben már láthattuk, hogy az eredményhalmazt csak rekordonként bejárva, rekordokon belül pedig mezőnként végigjárva kaphatjuk meg az egyes mezőket így feltétlenül tudnunk kell hogy a táblának pontosan hány darab oszlopa van. Ezt a ResultSetMetaData objektum getColumnCount() metódusával tudhatjuk, meg ami egy int típusú értékkel tér
vissza. Amennyiben nyomtatáshoz készítjük elő az eredményhalmazunkat akkor hasznos lehet a getColumnDisplaySize(int oszlop) metódus amely megadja az egyes oszlopok karakterben számolt maximális szélességét. A getColumnName(int oszlop) metódus az adott sorszámú oszlop nevét, míg a getColumnLabel(int oszlop) az adott sorszámú oszlop fejlécét adja meg, ezek különbözhetnek, ha a lekérdezésben aliasokat használunk. Amennyiben az eredményhalmaz mezőit valamely céllal fel is akarjuk dolgozni nélkülözhetetlen, hogy pontosan ismerjük az egyes mezők típusát. Ebben segítenek a . 34 Internetes adatbázis- kezelés getColumnType(int oszlop) és a getColumnTypeName(int oszlop ) metódusok, amelyek az adott oszlop SQL típusát illetve annak az adott adatforrásra jellemző nevét adják meg. A ResultSetMetaData objektum ezeken kívül még számos hasznos információról képes futás közben tájékoztatni minket, így pl. Tábla, Séma,
Katalógusnevekről vagy az adott oszlopra való megszorításokról, így lehet-e null érték, írható-e, stb Példa: try{ Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("select * from employee"); ResultSetMetaData rd = rs.getMetaData(); int colCnt = rd.getColumnCount(); String prop; String mneve,mtipusa; int mhossza; for(int i=0;i<colCnt;i++){ mneve = rd.getColumnName(i+1); mtipusa = rd.getColumnTypeName(i+1); mhossza = rd.getColumnDisplaySize(i+1); prop = "Mező"+(i+1)+": Neve:"+ mneve + " Típusa:"+ mtipusa + " Szélessége:"+ mhossza +" "; texta 1.append( prop ); } }catch(SQLException e){}; . 35 Internetes adatbázis- kezelés A példa bemutatja hogy hogyan kérdezhetjük le az eredményhalmazunk oszlopainak számát, majd ennek tudatában az egyes oszlopok jellemzőit lekérdezi és egy szövegmezőbe (java.awtTextArea) listát készít az eredményhalmaz szerkezetéről 2.6
Java tipusok és SQL tipusok megfeleltetése A JDBC meghajtók az SQL adattípusokat lehetőség szerint a szokásos Java adattípusokká kontertálják. Ezek a típusok használhatók az egyes oszlopok elérésénél a getXXX illetve setXXX metódusoknál. Fontos hogy tisztában legyünk az egyes típusok megfeleltetésével. SQL típus JAVA típus CHAR String VARCHAR String LONGVARCHAR java.ioInputStream NUMERIC java.sqlNumeric DECIMAL java.sqlNumeric BIT boolean TINYINT byte SMALLINT short INTEGER int BIGINT long REAL float FLOAT float DOUBLE double BINARY byte[] VARBINARY byte[] LONGVARBINARY java.ioInputStream DATE java.sqlDate TIME java.sqlTime TIMESTAMP java.sqlTimestamp . 36 Internetes adatbázis- kezelés 2.7 Tranzakciókezelés Ha Java JDBC tranzakciókezeléséről többet akarunk megtudni ahhoz a Connection interfészt kell még bővebben megvizsgálnunk. Egy adatbáziskapcsolatot ezen interfész segítségével a
korábbiakban leírt módon már létre tudunk hozni. Természetesen egy adatbázishoz egy időben több Connection objektumon keresztül is élhet kapcsolatunk, így meg kell oldanunk a tranzakciókezelés problémáit. 2.71 Tranzakciók érvényesítése és visszagörgetése A Connection objektumon át az adatbázisnak átadott minden egyes SQL utasítás egy tranzakció eleme. Legegyszerűbb esetben minden utasítás egy tranzakciónak felel meg Az adatbázis-meghajtók alapállapotban az adatbázisokat AUTOCOMMIT módban használják, azaz a táblákat módosító utasítások azonnal érvényre jutnak. Ez a Connection objektum setAutoCommit(boolean) metódusával állítható. Amennyiben ezt false értékre állítjuk a program során a Connection objektum commit illetve rollback metódusaival juttathatjuk érvényre módosításainkat illetve visszaállíthatjuk a módosítás előtti állapotot. Ez a lehetőség akkor használható, ha az adott DBMS támogatja, erről a
DatabaseMetaData supportsTransactions metódusának segítségével győződhetünk meg. A commit metódus meghívásával lezárjuk, míg a rollback metódus meghívásával visszagörgethetjük a tranzakciónkat. Arról hogy az adatbázisunk éppen autocommit módban van-e a getAutoCommit által visszaadott true/false érték informál minket. Példa: con.setAutoCommit(false); try{ PreparedStatement update1 = con.prepareStatement( "UPDATE AUTOK SET UT MEGREND = ? WHERE AU NAME LIKE ?"); update1.setInt(1, 5); . 37 Internetes adatbázis- kezelés update1.setString(2, "SKODA"); update1.executeUpdate(); PreparedStatement update2 = con.prepareStatement( "UPDATE AUTOK SET AU RAKTARON = AU RAKTARON - ? WHERE AU NAME LIKE ?"); update2.setInt(1, 5); update2.setString(2, "SKODA"); update2.executeUpdate(); con.commit(); }catch(SQLException e){con.rollback();}; con.setAutoCommit(true); A pédában egy autókereskedés eladásainál lehetséges
problémát oldjuk meg. Egy megrendelés felvétele és a raktár frissítése egy tranzakción belül kell megtörténjen egyébként az adatbázis inkonzisztens állapotba kerülhet. Az első lépésben feloldjuk az autocommit módot. Ezek után végrehajtjuk a két UPDATE utasítást, amit egy commit utasítással zárunk. Az update utasításokat egy kivételkezelő blokkba tehetjük, így ha valami probléma merül fel az update-ek közben akkor a rollback visszagörgeti a tranzakciónkat. 2.72 Tranzakcióizolációs szintek Ha a DBMS támogatja a tranzakciókezelést az izolációs szintek beállításával kezelhetjük a több tranzakció egyidejű futásával kapcsolatos problémákat. A Connection interfész adattagjai int tipusú konstans adattagok amelyek mind egy-egy izolációs szintet jelképeznek. TRANSACTION NONE: A tranzakció nem támogatott a DBMS által. . 38 Internetes adatbázis- kezelés TRANSACTION DEFAULT: Az alapértelmezés szerint használt
izolációs szint. Ezt a DatabaseMetaData getDefaultTransactionIsolation metódusa által visszaadott érték. TRANSACTION READ COMMITTED: Ha ezt az izolációs szintet választjuk, akkor a tranzakció lezárásáig nem engedi az adatok olvasását. A ’Dirty read’, azaz update utáni és commit előtti állapotban levő értékek olvasása nem engedélyezett. TRANSACTION READ UNCOMMITTED: Ezen az izolációs szinten az adatok olvasása akkor is engedélyezett, ha az adatok esetleg nem konzisztens állapotban vannak. Előfordulhat, hogy olyan állapotot látunk, amely nem végleges. /Dirty Read/ TRANSACTION REPEATABLE READ: Ezt a szintet akkor érdemes beállítanunk, ha azt szeretnénk, hogy a tranzakció során egyszer már beolvasott adatok a következő beolvasáskor is ugyanabban az állapotban legyenek. TRANSACTION SERIALIZABLE: Egy lekérdezés tartalma a tranzakció során nem változhat meg, azaz ilyen rekordot nem vihet fel másik tranzakció addig, amíg ezt le nem
zártuk. A megfelelő izolációs szintet a Connection objektum setTransactionIsolation metódusával állíthatjuk be, valamint az aktuális értéket a getTransactionIsolation segítségével tudhatjuk meg. Az izolációs szintekre vonatkozó az adott DBMS által támogatott lehetőségeinket szintén a DatabaseMetaData segítségével tudhatjuk meg. Meggyőződhetünk róla, hogy az általunk beállítani kívánt izolációs szint támogatott-e a DBMS által, ha meghívjuk a supportsTransactionIsolationLevel(int) metódust. A fenti példa vizsgálata során felmerülhet az a kérdés, hogy a fenti tranzakció futása közben egy másik tranzakció keretén belül egy raktári kimutatást készítünk, azaz kinyomtatjuk a raktáron levő SKODA típusú gépjárművek adatait, könnyen félrevezető kimutatást készíthetünk, így a kódot célszerű kiegészíteni a következőképpen. . 39 Internetes adatbázis- kezelés int currIsoLev = con.getTransactionIsolation(); if
(currIsoLev != TRANSACTION READ COMMITTED) if (supportsTransactionIsolationLevel(TRANSACTION READ COMMITTED )) setTransactionIsolation(TRANSACTION READ COMMITTED); Megvizsgáljuk, hogy mi az aktuálisan beállított izolációs szint és ha az nem a megfelelő akkor beállítjuk a megfelelő izolációs szintet. Mielőtt beállítjuk, megvizsgáljuk, hogy támogatja-e azt a DBMS. 2.8 SQL specifikus kivételek kezelése Az eddigi példáinkban is látható volt hogy egy adatbázis művelet esetén számos kivétel merülhet fel. Ezeket a kivételeket a Java kivétel-kezelési mechanizmusa szerint kezelhetjük. A JDBC ezen kivételes események között különbséget tesz aszerint hogy egy a program futása szempontjából végzetes esemény következett-e be, vagy pedig csak egy rendellenes jellel találta magát szemben. Az előbbieket mindig le kell kezelnünk valamilyen módon, míg az utóbbiakra is célszerű odafigyelnünk. 2.81 Az SQLException kivételkezelő osztály
Adatbázis kapcsolat esetén egy hiba bekövetkezésekor SQLException kivétel váltódik ki. Pl.: Ha valamilyen oknál fogva egy SQL utasítás nem hajtható végre, szintaktikailag hibás, timeout lejárt, típuskonverziós hibák stb. Ennek a hibaobjektumnak a jellemzőit a következő metódusok meghívásával kaphatjuk meg: . 40 Internetes adatbázis- kezelés getErrorCode(): A hiba kódját kapjuk meg. Általában az adatbázis által adott hibakód getSQLstate(): Az X/Open konvenció által meghatározott szöveget kapjuk az adott hibához. getNextException() /setNextExceeption/: Az SQL hibákat egymáshoz láncolva kapjuk meg, illetve mi magunk is egymáshoz láncolhatjuk azokat. 2.82 Az SQLWarning osztály Az adatbázis kapcsolat közben nem csak hibaüzeneteket, hanem SQLWarning figyelmeztető üzeneteket is kaphatunk. Ezeknek nincs hatása a program futására, így ezen üzenetek figyeléséről nekünk kell gondoskodnunk. Pl.: try { Class.forName
("Driver"); Connection con = DriverManager.getConnection ( url, "user name", "password"); figyelem(con.getWarnings ()); Statement stmt = con.createStatement (); ResultSet rs = stmt.executeQuery (query); rs.close(); stmtclose(); conclose(); } catch (SQLException exc) { . 41 Internetes adatbázis- kezelés while (exc != null) { System.outprintln ("!--------Exception---------!"); System.outprintln ("SQLState: " + excgetSQLState ()); System.outprintln ("Message: " + excgetMessage ()); System.outprintln ("ErrorCode: " + excgetErrorCode ()); exc = exc.getNextException (); System.outprintln ("-------------------------------"); } } catch (java.langException exc) { } } private static void figyelem(SQLWarning warn) throws SQLException { if (warn != null) { System.outprintln ("!-------Warning---------!"); while (warn != null) { System.outprintln ("SQLState: " + warngetSQLState ());
System.outprintln ("Message: " + warngetMessage ()); System.outprintln ("ErrorCode: " + warngetErrorCode ()); System.outprintln ("!---------------------------!"); warn = warn.getNextWarning (); } } } 2.9 A Database Metadata interfész A DataBase Metadata interfész az adatbázis egészéről nyújt számunkra információt. A DataBase Metadata interfész segítségével győződhetünk meg az adatbázis tulajdonságairól, amelyhez éppen kapcsolódtunk. Ez hatékony segítség lehet akkor, ha az alkalmazásunk nem feltétlenül egy rögzített adatbázishoz kapcsolódik, hanem esetleg futási időben dől el hogy melyik adatbázissal vesszük fel a kapcsolatot. Jól jöhet akkor is ha az alkalmazásunkat több különböző adatbázis-kezelővel akarjuk használni. Az . 42 Internetes adatbázis- kezelés adatbázis specifikus programrészleteket megírhatjuk úgy hogy futási időben a konkrét adatbáziskezelőnek megfelelő műveletet hajtsanak
végre. Az információhoz az interfész egyes metódusainak meghívásával juthatunk. A metódusok egy része logikai azaz megtudhatjuk hogy az adott adatbázis-kezelő támogatja-e a kívánt funkciót vagy sem. Vannak olyan metódusok, amelyek egy-egy ResultSet-et adnak eredményül. Ezeket a korábban ismertetett módon értékelhetjük ki Megjegyzés: A Javaról szóló bevezetőben olvasható volt hogy a Java interfészek nem csak absztrakt metódusokból állnak, hanem lehet bennük konstans is. Ez az interfész jó példa erre, ugyanis a metódusok eredményeinek kezelésére ez az interfész meghatároz számos konstanst. Ilyenek pl: public final static int columnNoNulls; public final static int columnNullable; Ezek a megfelelő helyeken azt jelentik, hogy az adott oszlop értékei lehetnek avagy nem lehetnek null értékek. A teljesség igénye nélkül valamilyen célszerű csoportosításra törekedve kiragadtam néhány metódust ezek közül amely bemutatja a
DataBaseMetadata használatában rejlő lehetőségeket: 2.91 A kapcsolat jellemzői: Ebbe a csoportba azokat az információkat soroltam amelyek az adatbázis-kapcsolat felvételekor dőlnek el. Megtudhatjuk hogy milyen meghajtó segítségével vettük fel a kapcsolatot, milyen usernévvel jelentkeztünk be az adatbázisba és ezzel a usernévvel milyen jogosultságaink vannak. . 43 Internetes adatbázis- kezelés String getDriverName() Az adott meghajtóprogram nevét adja meg. Ez jól jöhet ha a DriverManager esetleg több regisztrált meghajtó közül számunkra is ismeretlen módon választott. String getDriverVersion() A meghajtóprogram verziószámát adja meg. String getUserName() Az adott felhasználó felhasználói nevét adja meg. ResultSet getTablePrivileges(String kat, String séma, String tábla) Az adott katalógus adott sémájának adott táblájához való jogosultságot adja meg. Ezt a jogosultságot egy eredményhalmaz néhány mezőjének
kiértékelésével tudhatjuk meg. Ennek az eredményhalmaznak az egyik mezőjében találjuk meg a jogosultság megadóját, míg egy másikban a jogosultság típusát (SELECT, INSERT, UPDATE) sőt egy mező arról is tájékoztat minket hogy ez a jogosultság az adott felhasználó által továbbadható-e vagy sem. boolean allProceduresAreCallable() A metódus visszatérési értéke TRUE ha az adott felhasználó meghívhatja az összes létező tárolt eljárást, egyébként FALSE. boolean allTablesAreSelectable() Az előzőhöz hasonló azt vizsgálja hogy lekérdezheti-e az összes táblát. 2.92 A konkrét adatbázis jellemzői Miután tisztában vagyunk a kapcsolat paramétereivel a legfontosabb, hogy mindent megtudjunk az adatbázisról, amivel dolgozunk. Megtudhatjuk hogy milyen táblák, oszlopok, tárolt eljárások állnak a rendelkezésünkre. A megfelelő metódusok argumentumaiban mintasztringeket adhatunk meg, így kereshetünk is. . 44 Internetes adatbázis-
kezelés ResultSet getTables(String katalógus, String séma, String táblanév, String[] típusok) Ez a metódus táblák meghatározására való. A paraméterek megadásával tulajdonképpen egy szűrőfeltétel adunk meg. Ezek lehetnek null értékek is Ezeknek a szűrőfeltételeknek megfelelő összes táblát listázza nekünk ez a metódus. A típusok tömb elemei lehetnek pl.: ’TABLE’,’VIEW’, stb Egy eredményhalmazzal tér vissza a metódus amelynek minden eleme egy táblát ír le, ezeknek a rekordoknak a kiértékelésével nyerhetjük ki a számunkra fontos információt. Az eredmény ’tábla’ szerkezete: Mező neve Típusa Leírása TABLE CAT String Tábla katalógus (lehet null) TABLE SCHEM String Tábla séma (lehet null) TABLE NAME String Tábla neve TABLE TYPE String Tábla típusa REMARKS String Megjegyzés ResultSet getPrimaryKeys(String k, String s, String t) A fenntitől némileg eltérő eredményhalmazt kapunk amelyből
kinyerhetőek a tábla elsődleges kulcsára vonatkozó adatok. ResultSet getProcedures(String kat, String séma, String eljárásnév) A tárolt eljárásokat informálhatjuk le vele. A táblákhoz hasonló szerkezetű rekordképet kapunk a tárolt eljárásoknál is. ResultSet getColumns(String kat,String séma,String tábla,String oszlopnév) Egy adott tábla oszlopainak leírását adja vissza a következő formában: . 45 Internetes adatbázis- kezelés Mező neve Típusa Leírás TABLE CAT String Tábla katalógus (lehet null) TABLE SCHEM String Tábla séma (lehet null) TABLE NAME String Tábla neve COLUMN NAME String Oszlop neve DATA TYPE short SQL típus TYPE NAME String Az adatforrás által meghatározott típusnév COLUMN SIZE int Oszlop hossza. BUFFER LENGTH - Nem használják. DECIMAL DIGITS int Tizedes jegyek száma. NUM PREC RADIX int Számrendszer. NULLABLE int Tartalmazhat-e null értéket. ! Említett konstansok REMARKS
String Oszlop leíró megjegyzés. COLUMN DEF String Default oszlop érték. SQL DATA TYPE int Nem használt. SQL DATETIME SUB int Nem használt. CHAR OCTET LENGTH int Maximális bájtok száma. ORDINAL POSITION int Oszlop sorszáma a táblában. IS NULLABLE String Nullérték lehet-e. 2.93 Az adatbázis-kezelő jellemzői: A legtöbb információt magáról az adatbázis-kezelőről annak szolgáltatásairól, beállításairól tudhatunk meg. Lekérdezhetjük az adatbázis-kezelő típusát, verziószámát Megtudhatjuk, hogy bizonyos feladatokat meg tudunk-e oldani az adott adatbáziskezelővel vagy sem. String getDatabaseProductName() Az adatbázis-kezelő termék nevét adja meg. . 46 Internetes adatbázis- kezelés String getDatabaseProductVersion() A termék verziószámát tudhatjuk meg. int getDefaultTransactionIsolation() A korábbiakban már szó volt arról hogy egy Java tranzakció egyik legfontosabb jellemzője a tranzakció izolációs szint.
Sok esetben célszerű az adatbázis-kezelő által alapértelmezett izolációs szintet választanunk. Ezzel a metódussal megtudhatjuk, hogy mi ez az izolációs szint. boolean supportsTransactionIsolationLevel(int) Amennyiben egy konkrét izolációs szintet akarunk alkalmazni meg kell győződnünk arról hogy az az izolációs szint támogatott-e az adatbázis-kezelő által. Az adott izolációs szintek kezelésére is (integer) konstansokat használ a JDBC. int getMaxColumnNameLength() Amennyiben az adott adatbázis-kezelőben korlátozva van az oszlopnevek hossza ezen metódus segítségével tudhatjuk meg ezt. int getMaxColumnsInGroupBy() Megadja hogy legfeljebb hány oszlop állhat a GROUP BY után. int getMaxColumnsInIndex() Megadja hogy legfeljebb hány oszlopból állhat egy index. int getMaxTablesInSelect() int getMaxColumnsInSelect() Megtudhatjuk hogy egy SELECT-ben hány táblából és hány oszlopot kérdezhetünk le, amennyiben az korlátozva van az adott
adatbázis-kezelőben. int getMaxColumnsInTable() Megadja hogy egy táblának maximum hány oszlopa lehet. int getMaxConnections() Megadja hogy egyszerre hány aktív kapcsolat hozható létre az adatbázissal. . 47 Internetes adatbázis- kezelés String getSQLKeywords() Több adatbáziskezelőnek vannak egyéni az SQL92 szabványtól eltérő kulcsszavai. Ennek a metódusnak a meghívásával ezen SQL kulcsszavaknak a vesszővel elválasztott listáját kapjuk meg. String getURL() A korábban már említett adatbázis URL kérdezhető le ennek a metódusnak a segítségével. boolean nullsAreSortedAtEnd(), boolean nullsAreSortedAtStart() A különböző adatbázis-kezelők különbözőképpen viselkednek, ha olyan oszlop szerint rendezve kérjük a listát amely tartalmaz NULL értékeket is. Attól függően, hogy az adott adatbázis-kezelő a lista végére vagy elejére teszi-e a NULL értékkel rendelkező rekordokat kapunk a fenti függvények esetén true, vagy false
értéket. boolean supportsAlterTableWithAddColumn(), boolean supportsAlterTableWithDropColumn() Ezen metódusok megadják hogy lehet-e ALTER TABLE utasítással az adatbázis valamely táblájához újabb oszlopokat felvenni vagy éppen törölni abból oszlopokat. boolean supportsColumnAliasing() Megadja hogy lehet-e oszlopokhoz alias neveket hozzárendelni. boolean supportsConvert() Megtudhatjuk hogy az adattípusok konvertálása (CONVERT) támogatott-e az adott adatbáziskezelő-rendszerben. boolean supportsDataDefinitionAndDataManipulationTransactions() Nem minden adatbázis-kezelő teszi lehetővé hogy egy tranzakció kellős közepén adatdefiníciós (DDL) vagy adatmanipulációs (DML) utasításokat is végrehajtsunk. Így ha ilyen műveleteket akarunk végezni előtte ezzel a metódussal célszerű erről meggyőződnünk. . 48 Internetes adatbázis- kezelés boolean supportsDataManipulationTransactionsOnly() Ha az előző szituációban csak a DML utasítások
támogatottak akkor ez a metódus TRUE értékkel tér vissza. boolean supportsFullOuterJoins(), boolean supportsLimitedOuterJoins() Megadják hogy az adott adatbázis-kezelőben a külső-join teljesen vagy csak korlátozottan támogatott-e. boolean supportsMultipleResultSets() Megadja hogy egy SQL utasítás végrehajtása után több eredménytáblát is visszakaphatunk-e. boolean supportsMultipleTransactions() Megtudhatjuk hogy támogatott-e a több nyitott tranzakció egy időben állapot. boolean supportsUnion() Megadja hogy a UNION támogatott-e. Az itt említett metódusokon kívül még sok egyéb metódus áll rendelkezésünkre az adatbázis további jellemzőinek felderítésére. Ezeket a megfelelő dokumentumokban megtaláljuk. Példa: A példa applet egy adatbáziskapcsolat felépítésére ad lehetőséget. A Driver, adatbázis URL, felhasználói név és jelszó megadásával tetszőleges adatbázishoz kapcsolódhatunk, majd erről az adatbázisról tudunk meg
információkat a fent említett módszer alkalmazásával. Kódrészletek a B/0 mellékletben. Teljes forrás: MetadataTest.java Az applet működés közben A/0 melléklet. A példa tesztelése egy SQL Anywhere példaadatbázis adatainak lekérdezésével történt. . 49 Internetes adatbázis- kezelés 3. Esettanulmány Az előző fejezetben ismertetésre került egy olyan technológia melynek használatával olyan alkalmazásokat készíthetünk, amelyek Intranet vagy akár Internetes környezetben működnek és amelyek mögött tetszőleges adatbázis-kezelő lehet. Nehéz ma azt megállapítani, hogy hol, milyen környezetben milyen feladatok megvalósítására alkalmas ez a technológia, hiszen a Java nyelv lehetőségei napról napra változnak. Az még mindenképpen elmondható hogy kevés a teljes egészében erre a technológiára építő alkalmazás. Ennek az oka lehet az hogy a Java applet technológia sebességében még elmarad az egyéb lehetőségektől.
Ebben a fejezetben egy olyan alkalmazási esettanulmányt vizsgálunk meg ahol talán már ma is létjogosultsága van ennek. Az előző fejezet összefoglalásaképpen elmondható, hogy ha az Internetes alkalmazásunkhoz a Java JDBC csomagjának lehetőségeit akarjuk használni, akkor a megfelelő Java fejlesztőkészlet – ami az Interneten ingyenesen beszerezhető, pl. a SUN honlapján – beszerzése után a használni kívánt adatbázis-kezelő specifikus meghajtót – szinte mindegyik adatbázis-kezelőhöz találunk meghajtókat az Interneten - kell beszereznünk. Ezen eszközök segítségével nekiláthatunk alkalmazásunk elkészítéséhez Ami a JDBC nagy előnye, hogy egy egységes kezelőfelületet – egy interfész csomagot – nyújt a programozó felé, amelyet adatbázis-kezelőtől függetlenül programozhatunk akár anélkül hogy tudnánk hogy milyen konkrét adatbázissal fogunk dolgozni. Amennyiben olyan meghajtónk van ami több adatbázis-kezelő
meghajtására alkalmas, vagy több meghajtóval rendelkezünk a különböző adatbázis-kezelőkhöz egyidőben több adatbáziskezelővel is együtt dolgozhatunk Ez még tovább fokozható ha belegondolunk hogy a DataBaseMetaData segítségével futási időben dönthetünk arról hogy adott adatbáziskezelő esetén milyen műveleteket kívánunk végrehajtani. Sőt írhatunk olyan alkalmazásokat, amelyekben a felhasználó dönthet nem csak arról hogy melyik adatbázisból de arról is hogy pontosan milyen adatokkal kíván dolgozni. Az alábbi esettanulmányban ez utóbbi lehetőségek kihasználására törekszünk. A mai adatbázis-kezelők nagy része tartalmaz olyan segédprogramokat, amelyek az adatbázisban található adatok lekérdezésére szolgálnak. A legjobb adatbázis-kezelő rendszerek mellé – lásd. ORACLE, MS SQL Server - fejlett grafikus felületű könnyen . 50 Internetes adatbázis- kezelés használható interaktív lekérdező felületeket
mellékelnek. Ezek egyetlen hátránya, hogy általában csak a saját adatbázis-kezelőjük adatbázisaival boldogulnak. Így az Oracle eszközeit csak Oracle az MS SQL Server eszközeit csak MS SQL Server környezetben használhatjuk. Egy olyan esetben ahol esetleg több adatbázis-kezelő adatbázisait akarjuk lekérdezni mindegyikhez a saját segédeszközét kell használnunk. A Java JDBC egy megoldást szolgáltathat erre a problémára, hiszen ha ennek segítségével készítünk egy Interaktív lekérdező felületet, majd ezt felszereljük a megfelelő adatbázis-kezelők meghajtóival máris egy univerzális lekérdező rendszert kapunk. A másik jelentősége ennek hogy ha ezt az alkalmazást egy Web-szerveren installáljuk onnantól kezdve ezt nem kell magunkkal cipelnünk hiszen bármilyen platformon bármely gép előtt ülve egy Internet kliens szoftver (browser) segítségével installálás nélkül használhatjuk azt. 3.1 Feladat meghatározása A bevezetőben
említett okokból célunk egy Internetes interaktív univerzális lekérdező rendszer létrehozása, amely a következő elvárásoknak eleget tesz: • Tetszőleges adatbázishoz képes kapcsolódni amelyhez rendelkezünk felhasználói • • • • jogosultsággal. Csak a megfelelő jogosultsággal rendelkező felhasználók kapcsolódhatnak az adott adatbázisokhoz. A lekérdező rendszer vizuális segítséget nyújt lekérdezéseink összeállítására. A lekérdező rendszer támogatást nyújt az adatbázis szerkezetének feltérképezésére, azaz az általunk teljesen ismeretlen szerkezetű adatbázisokban való tájékozódásra. A lekérdezés eredményeit megfelelő jól átlátható formában jeleníti meg. . 51 Internetes adatbázis- kezelés 3.2 A feladat elemzése A feladat három jól elkülöníthető részre tagolható. Ezek: • • • Kapcsolatfelvétel a megfelelő adatbázissal Az SQL lekérdezés (SELECT) összeállítása Az adatok
megjelenítése 3.21 Kapcsolatfelvétel az adatbázissal A feladatnak ezzel a részével van a legkevesebb gondunk, hiszen nekünk nem kell azzal törődnünk, hogy milyen adatbázishoz fogunk kapcsolódni. Ahhoz hogy megfelően működjön az alkalmazás az adatbázis-kezelőnek megfelelő meghajtót kell találnunk és installálnunk. A meghajtók installálása és használata (adatbázis URL megadásának módja) a meghajtókhoz mellékelt leírásokból megtudható. A felhasználótól be kell kérnünk a megfelelő meghajtó osztály-hivatkozást, az adatbázis URL-t valamint felhasználó azonosítót és jelszót. A felhasználói név és jelszó szükségessége biztosítja azt hogy arra nem jogosult felhasználó ezzel az eszközzel sem juthat az adatok birtokába. Egyébként egy ilyen Internetes alkalmazás esetében ez komoly problémákat is okozhatna. Ez a megoldás az adatbázis-kezelő felhasználó azonosítási lehetőségeit használja ki. Az adatbázis
kapcsolat felvétele a korábbiakban bemutatott példákhoz hasonlóan történik. Az ide vonatkozó kódrészlet a B/1 függelékben míg a felhasználói képernyő a A/1 függelékben található. 3.22 Az SQL lekérdezés összeállítása Miután sikeresen felvettük az adatbázissal a kapcsolatot (sikeresen teszteltük) össze kell állítanunk az adatbázis-kezelőnek átadni kívánt SELECT mondatot. Erre két lehetőséget biztosít az alkalmazás. Ha tisztában vagyunk az igényünkkel az adott SELECT mondatot . 52 Internetes adatbázis- kezelés begépelhetjük. Amennyiben nem tudjuk pontosan megfogalmazni a SELECT mondatunkat segítségül hívhatjuk az alkalmazás lekérdezés összeállítást segítő részét. Kódrészlet: B/2. Felhasználói felület: A/2 A lekérdezés összeállításának lépései: • • • • • A lekérdezés összeállításakor az első feladatunk a forrás táblák és ezek szükséges mezőinek kijelölése. Ezt a
korábbiakban megismert DatabaseMetaData osztály segítségével tudjuk megtenni. Lásd B/3, A/3 Szűrőfeltétel megadása. /WHERE/ Lásd B/4, A/4 Csoportosítás megadása /GROUP BY/ Lásd B/5, A/5. Rendezési feltétel meghatározása. Lásd B/6, A/6 Az SELECT mondat felépítése Lásd B/7, A/7 Megjegyzés: A fennti pontok és így maga az alkalmazás sem tartalmaz néhány olyan eszközt amellyel esetleg egyes lekérdezések összeállításakor számolnunk kell. Így az egyes táblák kiválasztásakor akkor járunk el teljesen korrekt módon ha a táblákat tulajdonosukkal együtt tartjuk nyilván és így azonosítjuk őket. Ez egyébként a DatabaseMetaData segítségével megoldható probléma. Másik problémás kérdés a különböző típusú JOIN-ok összeállításának támogatása. Ennek megvalósítása nem könnyű feladat mert ez az pontja a SELECT mondatok szintaktikájának ahol az egyes adatbázis-kezelők gyökeresen eltérhetnek (lásd MS SQL Server kontra
ORACLE). De tovább sorolhatnánk még számos SQL szintaktikai elemet. Ezek ennek az alkalmazásnak a továbbfejlesztési irányába mutatnak. Jelen esetben is áthidalható ezek hiánya az összeállított SELECT mondatunk manuális szerkesztésével. . 53 Internetes adatbázis- kezelés 3.23 A lekérdezés eredményének megjelenítése Az elkészült SELECT mondatunkat tesztelhetjük. Amennyiben sikerült szintaktikailag és szemantikailag is helyes SELECT mondatot összeállítanunk futtathatjuk azt és megtekinthetjük lekérdezésünk eredményét. Az eredményt az ilyen célú segédprogramokhoz hasonlóan egyszerű táblázatos formában tekinthetjük meg. Az alkalmazás egy plusz szolgáltatása hogy az eredményhalmazt nem egy ütemben dolgozza fel. Megadhatjuk, hogy hány rekordot akarunk egyben látni és a lekérdezés futtatásakor csak ennyi rekordot dolgozunk fel egy ütemben. Ez fokozottan érdekes egy ilyen alkalmazás esetén, hiszen a Java alkalmazások
egyébként sem a gyorsaságukról híresek. Ezt két különböző módon oldhatjuk meg. Az egyik megoldás hogy egyben lekérdezzük a teljes eredményhalmazt majd az általunk megszabott méretű részletekben dolgozzuk fel. Ez azonban csak félmegoldás, hiszen az eredményhalmaz lekérdezése is jelentős időtartamot vehet igénybe. A tökéletes megoldás hogy az eredményhalmaz lekérdezése is csak részben történik meg majd a felhasználó kérheti a lekérdezés további rekordjainak lekérdezését. Erre a Statement objektumnak vannak is használható metódusai A setMaxRows(int) / getMaxRows() metódusokkal beállíthatjuk az egy ütemben lekérdezni kívánt rekordok számát. A getMoreResults() metódussal pedig további eredményrekordokat kérhetünk le. Ennek a metódusnak a visszatérési értéke boolean típusú, amely megadja hogy van-e még az eredményhalmaznak további rekordja. Az ide kapcsolódó kódrészletek a B/8, A/8 függelékben. . 54
Internetes adatbázis- kezelés 4. Kitekintés Az előző fejezetekben több ízben hangsúlyozásra került hogy ez a bemutatott technológia nem minden esetben a legcélravezetőbb, de arról még nem volt szó hogy milyen lehetőségeink vannak még. Ennek kielégítő tárgyalása egy másik dolgozat témája lehetne, ennek a dolgozatnak nem is célja, hogy az egyéb létező technológiákat részletesen bemutassa. Ez a fejezet mindössze olyan céllal került a dolgozatba hogy egy alternatívát vagy inkább egy másik technológiai alapelvet bemutasson ami egyébként a gyakorlatban ma még mindenképp népszerűbb és gyakrabban alkalmazott. A Java Applet technológia talán legnagyobb gyengéje a sebessége. A lassúság mögött több minden is meghúzódik. Az egyik ok a Java osztálybetöltő mechanizmus, amely jelentősen lassíthatja egy Java alkalmazás működését, hiszen először meg kell találnia az osztálybetöltőnek a megfelelő class fájlt, majd miután
megvan azt a kliensre kell letöltenie. Az alkalmazás – pontosabban applet – a kliensen fut, azaz minden szükséges információt le kell tölteni a kliensre. Minden adatbázis művelet esetén a kliensnek kell felvennie a kapcsolatot az adatbázis-kezelővel. Mindez rámutat, hogy egy Java applet futtatása jelentős hálózati forgalommal jár együtt, ami nagyobb távolságok esetén érthetően lassú futást eredményezhet. Persze mindez igaz a LAN környezetre készült kliens-szerver alkalmazásokra is csak a távolságbeli különbségek fokozottan jelentkeznek. 4.1 Internetes adatbázis-kezelés másképpen A most említésre kerülő technológiai irányvonalba való betekintéshez meg kell ismerkednünk két eddig nem emlegetett fogalommal. Az egyik az ASP (Active Server Pages) a másik pedig az ADO (ActiveX Data Objects), ahol az előbbire elsősorban az Internetes felület kidolgozásánál lesz szükségünk, míg az utóbbi egy adathozzáférési technológia,
amelyet kellemesen használhatunk egy Internetes alkalmazás készítésekor az adatbázishoz kapcsolódó funkciók ellátására. . 55 Internetes adatbázis- kezelés 4.2 ASP röviden Az ASP egy olyan scriptnyelv amellyel olyan Web oldalakat fejleszthetünk amelyek dinamikusak - de itt én inkább az aktív kifelyezést használnám, a név is erre utal – és ami nagyon fontos hogy a dinamizmus a szerver oldalon történik. Egy ASP Web oldal mögött egészen más tartalom van a szerver oldalon mint a kliens oldalon. Ez azért van mert a Web szerveren tárolt ASP fájl szerkezete és tartalma eléggé sajátos. Ez azt jelenti, hogy egy ASP forrás tartalmazhat a HTML-ben már megszokott elemeket, szinte tetszőleges script nyelven írt scripteket (pl. JavaScript, VBScript,) és ezen felül olyan forrásrészeket is találunk amelyek eddig egy HTML forrásban nem fordultak elő. Anélkül hogy elmerülnénk a részletekbe ezen ASP specifikus forrásrészek főbb jellemzője
hogy ezek a részek kiértékelődnek akkor amikor egy kliens (browser) kérés érkezik feléjük, ezen kiértékelés eredménye mindig egy-egy HTML szintaktikának megfelelő forrás lesz és az így összeállt immáron teljesen HTML forráskódra emlékeztető forrást küldi át a Web Szerver a kliens browsernek. Így ha a kliens browserben megtekintünk egy ASP forrást semmi ASP-re utaló jelet nem találunk. Ennek az ASP nyelvnek megvannak a maga nyelvi elemei, objektumai, lehet vele változókat kezelni. 4.3 ADO adathozzáférési technológia A másik kérdés hogy hogyan lehet ezzel a technológiával adatbázis-kezelést végrehajtani. Erre az ADO adja meg a választ Az ADO egy objektum felület az OLE DB felett. Az adatforrások nagy része – ez lehet Excel táblázat, relációs adatbázis-kezelő, stb- el van látva egy ún. OLE DB provider felülettel, amely lehetővé teszi az adott adatforrás mögött levő tartalom és szolgáltatáshalmazhoz való
hozzáférést. Ezeket általában az adatforrások szállítói készítik el. Ez a felület is programozható, azonban nagyon bonyolult ennek programozása. Ezért dolgozta ki a Microsoft az ADO univerzális adathozzáférési technológiát, amely az összes ilyen OLE DB provider feletti könnyen programozható objektum orientált réteg. Az ADO objektummodellje három fő objektumra épít, ezek a : Connection, Command, ResultSet objektumok. A RecordSet reprezentálja az adatokat, a Connection az adatforrással felépített kapcsolatot, végül a Command egy parancsot amely lehet például egy SQL Statement. . 56 Internetes adatbázis- kezelés Az ADO adathozzáférési technológia kellemesen használható nagyjából tetszőleges fejlesztő környezetben így az ASP scriptjeinkben is. 4.4 Architektúra Ezen lehetőségek alkalmazásával teljesen új architektúrát építhetünk fel. Egy Internetes alkalmazás folyamatai a következő ábrán követhetők végig. Kliens
kérés Kliens Browser Web Szerver Szerver oldali adathozzáférés HTML, DHTML, kliens script Kliens oldali adathozzáférés Adatbázis szerver A fenti rajzon is látszik hogy két lehetőségünk van az adatbázis-kezelés megvalósítására. Az egyik hogy a kliens oldalon vesszük fel a kapcsolatot az adatbázissal hasonlóan a Java Appleteknél is megismertekhez, vagy pedig a szerver oldalon. 4.5 Szerver oldali adathozzáférés A szerver oldali adathozzáférés lényege hogy a kliens kérését szerver oldali scriptek dolgozzák fel, így az adatbázis specifikus műveletek is a szerver oldalon hajtódnak végre. Folyamat: • • • A kliens egy kéréssel fordul a Web Szerverhez (pl. egy form kitöltésével) A Web Szerver továbbítja a kérést az adatbázis-kezelő felé Az adatbázis-kezelő teljesíti a kérést, pl. összeállítja a ResultSet objektumot és átadja a Web Szervernek . 57 Internetes adatbázis- kezelés • A Web Szerver szerveroldali
scriptek segítségével feldolgozza ezt, majd az ASP eszközeivel összeállít egy HTML forrást amely már statikusan tartalmazza az adott adatokat és átküldi azt a kliens felé. Hátránya: A ResultSet objektum nem őrződik meg két kérés között így azt minden új kérés után újra kell építeni. 4.6 Kliens oldali adathozzáférés A szerver oldali adathozzáféréssel ellentétben itt az adatbázishoz való csatlakozás és az egyéb adatbázis műveletek is kliens oldalon történnek kliens oldali scriptek segítségével. A kliens oldali hozzáférés megoldja a fenti problémát hiszen ebben a módszerben a ResultSet a kliens oldalon keletkezik, nincs is on-line kapcsolatban az adatbázis-kezelővel így azt nem feltétlenül kell megszüntetni minden művelet után. Az ADO nagyon sok támogatást nyújt ennek a megvalósítására támogatja nemcsak a ResultSet objektumok kliens oldalra történő lecsatolását hanem elmenthetjük ezeket később pedig
elővehetjük őket vagy megoldható az is hogy egy ResultSet néhány rekordjának módosítása után csak a módosított rekordokat küldjük vissza az adatbázis-kezelőnek. . 58 Internetes adatbázis- kezelés 4.7 Példa Ebben a példában az ASP néhány eszközét tekinthetjük át valamint láthatunk egy egyszerű ADO alapú adatbázis-lekérdezést. A szerver oldali ASP –Pelda.asp- forráskódja: <html><head> <TITLE>Pelda.asp</TITLE> </head> <body bgcolor="#FFFFFF"> <% az adatbázis kapcsolódás paraméterei myDSN="DSN=BUNDY;uid=tom;pwd=tom" set conn=server.createobject("adodbconnection") az adatbáziskapcsolat megnyitása conn.open myDSN az adatbázislekérdezés megadása mySQL="select emp id, fname, lname from employee where job id = 5" a lekérdezés futtatásának eredménye egy ResultSet set rs=conn.execute(mySQL) meg kell vizsgálnunk hogy van-e eredményrekordunk If rs.eof
then response.write "Nincs találat rekord:<br>" response.write mySQL & "<br>" connection.close set connection=nothing response.end end if . 59 Internetes adatbázis- kezelés %> <table border=1> <% Elkészítjük az eredményhalmaz fejlécét response.write "<tr>" for each whatever in rs.fields response.write "<td><B>" & whatevername & "</B></TD>" next response.write "</tr>" Feldolgozzuk az eredményhalmazt DO UNTIL rs.eof A mezőket változókba töltjük emp id=rs("emp id") fname=rs("fname") lname=rs("lname") Majd elkészítjük a browser felé a megjelenítést, egyszerű táblázat formájában cellstart="<td align=""top"">" response.write "<tr>" response.write cellstart & emp id & "</td>" response.write cellstart & fname &
"</td>" response.write cellstart & lname & "</td>" response.write "</tr>" A következő rekordra lépünk rs.movenext LOOP %> </table> . 60 Internetes adatbázis- kezelés <% A megfelelő objektumokat lezárjuk rs.close set rs=nothing conn.close set conn=nothing %> </body></html> Megfigyelhetjük hogy az ASP nyelvi eszközei a HTML forráskód ’generálására’ tartalmaznak vezérlési szerkezeteket – for, do-until, if-then -, szövegmanipuláló eszközöket, mint a response amellyel ki lehet írni stringeket a HTML forrásba . Az ADO objektumai közül ebben a példában a Connection – amely az adatbáziskapcsolat felvételére szolgál – és a ResultSet – az eredményhalmaz kezelésére – objektumokkal ismerkedhettünk meg. Végül nézzük meg hogy milyen kliens oldali HTML kódot generált ez az ASP. HTML forrás: <html><head> <TITLE>Pelda.asp</TITLE>
</head> <body bgcolor="#FFFFFF"> <table border=1> <tr><td><B>emp id</B></TD><td><B>fname</B></TD><td><B >lname</B></TD></tr> <tr><td align="top">PXH22250M</td><td align="top">Paul</td><td align="top">Henriot</td></tr> <tr><td align="top">CFH28514M</td><td align="top">Carlos</td><td align="top">Hernadez</td></tr> <tr><td align="top">JYL26161F</td><td align="top">Janine</td><td align="top">Labrune</td></tr> . 61 Internetes adatbázis- kezelés <tr><td align="top">LAL21447M</td><td align="top">Laurence</td><td align="top">Lebihan</td></tr> <tr><td
align="top">RBM23061F</td><td align="top">Rita</td><td align="top">Muller</td></tr> <tr><td align="top">SKO22412M</td><td align="top">Sven</td><td align="top">Ottlieb</td></tr> <tr><td align="top">MJP25939M</td><td align="top">Maria</td><td align="top">Pontes</td></tr> </table> </body></html> . 62 Internetes adatbázis- kezelés Irodalomjegyzék Hálózati alkalmazások készítése /CORBA, Java, WWW/ Csizmadia Balázs, Kalibán Kiadó Budapest, 1998. Java 1.1 Útikalauz programozóknak Szerk:Nyékyné Gaizler J, Kolozsik T, Lakatos A, ELTE TTK Hallgatói Alapítvány Kiadó, Budapest, 1997. Thinking in Java by Bruce Eckel, Mind Wiew Inc,1997 http://www.EckelObjectscom/Eckel/ Adatbázis-kezelés Jávában
http://www.eunethu/infopen/cikkek/java/jdbchtml A Java programozási nyelv Kiss István Infopen 1996 http://www.eunethu/infopen/ http://www.mmtbmehu/~kiss Java API specifikáció http://javasoft.com/products/api-overviewhtml JavaBeans Development Kit. http://javasoft.com/beans/ JavaSoft JDBC homepage http://www.Javasoftcom/jdbc/ Java Tutorial http://java.suncom/books/Series/Tutorial/ Openlink JDBC http://www.openlinkswcom/ . 63 Internetes adatbázis- kezelés The JDBC(TM) API Version 1.20 http://splash.javasoftcom/jdbc/ Java Felhasználók Társasága http://javasite.bmehu Java Programer’s FAQ http://www.afucom/javafaqhtml JDBC – Java Acces to SQL Database http://mindprod.com/jdbchtml JDBC(tm) drivers http://java.suncom/products/jdbc/jdbcdrivershtml MindQ’s Java Training Online http://www.mindqcom/java . 64 Internetes adatbázis- kezelés A függelék A/0 A MetaDataTeszt applet működése A kapcsolódásnál a megfelelő paramétereket megadva – driver, url,
username, password – kapcsolódhatunk az adatbázishoz, majd a DatabaseMetaData interfész lehetőségeinek kihasználásával információkat tudhatunk meg az adatbázis-kezelőről. . 65 Internetes adatbázis- kezelés A/1 Az adatbázis-kapcsolat felépítése Az adatbázishoz való kapcsolódáshoz egy meghajtót egy adatbázis url-t, felhasználói azonosítót és jelszót kell megadnunk. Az adatbázis-kapcsolatot tesztelhetjük Itt egy MS SQL Server adatbázishoz való kapcsolódást láthatunk, ez a kapcsolat egy Weblogic meghajtó segítségével épül fel melynek próbaverziója letölthető az Interneten. . 66 Internetes adatbázis- kezelés A/2 Lekérdezés összeállítás A lekérdezést egyenesen megadhatjuk, vagy a Szerkesztés gombra kattintva kapunk az összeállításhoz vizuális segítséget. Mielőtt a lekérdezést futtatnánk tesztelhetjük azt. . 67 Internetes adatbázis- kezelés A/3 A lekérdezés tábláinak és mezőinek a
meghatározása A táblák kiválasztása után az oszlopok lapon a kiválasztott táblák mezőit választhatjuk ki. A kiválasztott mezők tablanév és oszlopnév szerint kerülnek tárolásra. . 68 Internetes adatbázis- kezelés A/4 Szűrőfeltétel megadása Szűrőfeltételeket határozhatunk meg, a felhasználni kívánt oszlopokat a listából kiválasztva is beszúrhatjuk. Több szűrőfeltétel meghatározása esetén ezek kapcsolatát az AND, OR és a zárójeleket beszúró gombok segítségével adhatjuk meg. . 69 Internetes adatbázis- kezelés A/5 Csoportosító oszlopok meghatározása A csoportosítás a már a korábbiakban rögzített oszlopok szerint történhet. . 70 Internetes adatbázis- kezelés A/6 Rendező oszlopok kijelölése Az oszlopokat amelyek szerint rendezni akarunk a korábban kiválasztott oszlopok közül jelölhetjük meg. A rendezési oszlopokat, azaz a rendezés sorrendjét a FEL, LE gombokkal szabályozhatjuk.
Oszloponként meghatározhatjuk, hogy az azon oszlop szerinti rendezés növekvő vagy csökkenő legyen. . 71 Internetes adatbázis- kezelés A/7 A SELECT mondat összeállítása Az utolsó lapon megtekinthetjük az így összeállt lekérdezésünket és még javításokat is végezhetünk rajtuk még mielőtt átadnánk azt az appletnek listázásra. . 72 Internetes adatbázis- kezelés A/8 Listázás Az applet utólsó lapján megadhatjuk, hogy hány rekordot listázunk egyszerre, majd a Select gombra klikkelve listázhatjuk az eredményt. Amennyiben még nincs vége az eredményhalmaznak, további sorokat kérhetünk a Tovább gombra kattintva. A listázó ablakban fejlécet is láthatunk amelyet alias nevek használatával a szánk íze szerint alakíthatunk. . 73 Internetes adatbázis- kezelés B függelék B/0 A DatabaseMetaData bemutatására készült applet kódrészletei import import import import import import import java.awtFont;
java.awtFontMetrics; java.awtRectangle; java.awtInsets; java.langMath; java.langString; java.sql*; class MetadataTest extends java.appletApplet implements java.awteventActionListener { public MetadataTest() { super(); } //Az applet Form felépítése, egyéb szükséges metódusok, lsd. a teljes forrásban public void cb conn actionPerformed( java.awteventActionEvent event ) { /* * adatbáziskapcsolat felépítése * */ String driver = textf driver.getText(); String url = textf url.getText(); . 74 Internetes adatbázis- kezelés String uid = textf uname.getText(); String passwd = textf pwd.getText(); try { Class.forName( driver ); con = DriverManager.getConnection(url, uid, passwd ); textf conn.setText("A kapcsolatfelvétel sikerült!"); cb metadata.enable( true ); }catch(java.sqlSQLException exc){ textf conn.setText( "A kapcsolatfelvétel nem sikerült: A kapcsolat paraméterei nem megfelelőek!" ); } catch(java.langClassNotFoundException exc){ textf
conn.setText( "A kapcsolatfelvétel nem sikerült: Nem megfelő driver!"); }; } public void cb metadata actionPerformed( java.awteventActionEvent event ) { /* * a Metadata használata * */ try{ md = con.getMetaData(); textf db.setText(mdgetDatabaseProductName()); textf dbver.setText(mdgetDatabaseProductVersion()); textf maxcon.setText(""+mdgetMaxConnections()); textf triz.setText(""+mdgetDefaultTransactionIsolation()); . 75 Internetes adatbázis- kezelés //az adatbázis tábláinak lekérdezése java.langString[] types = {"TABLE"}; ResultSet rs = md.getTables(null,null,null,types); //paraméterek: //katalógus megadása //séma minta, //táblanév minta (a null érték esetben az összes táblát //lekérdezzük) //tipus: lehet tábla, view,.,egy sztring tömbben //határozhatjuk meg while (rs.next()) lb tablesaddItem( rsgetString(3) ); //Az eredményhalmaz rekordjainak mezői a táblát jellemző //adatok //pl. név, tulajdonos, itt a
neveket kérdezzük le és //ListBoxban jelenítjük meg }catch(java.sqlSQLException exc){}; } public void cb mez actionPerformed( java.awteventActionEvent event ) { /* * adott tábla mezőinek lekérdezése * */ if ( lb tables.getSelectedIndex()!=-1){ lb mez.clear(); String t name = lb tables.getSelectedItem(); try{ ResultSet rs = md.getColumns(null,null,t name,null); . 76 Internetes adatbázis- kezelés //a harmadik paraméterben adhatjuk meg a tábla nevét while (rs.next()) lb mezaddItem( rsgetString(4)); }catch(java.sqlSQLException exc){}; } } /* * adattagok */ Connection con; DatabaseMetaData md; /* egyéb adattagok / } . 77 Internetes adatbázis- kezelés B/1 Az adatbázis-kapcsolat felvétele class Ijsql page 1 extends java.awtPanel implements java.awteventActionListener { /* / public void cb teszt actionPerformed( java.awteventActionEvent event ) { parentForm.driver = textf 1getText(); parentForm.url = textf 2getText(); parentForm.uname = textf 3getText();
parentForm.pwd = textf 4getText(); try { Class.forName( parentFormdriver); Connection conn = DriverManager.getConnection( parentFormurl, parentForm.uname, parentFormpwd); textf 5.setText( "Az adatbáziskapcsolat felvétel sikeresen megtörtént!"); conn.close(); }catch(SQLException e){ textf 5.setText( "Az adatbáziskapcsolat felvétel sikertelen: "+e.toString()); }catch(ClassNotFoundException c){ textf 5.setText("Nincs ilyen meghajtó:”+ parentFormdriver); } } /* / } A Teszt gombra kattintva beállítjuk az adatbázis-kapcsolat paramétereit, amelyek az Ijsql applet osztály tagváltozói, amelyre itt a parentForm –mal hivatkozunk. . 78 Internetes adatbázis- kezelés B/2 Lekérdezés összeállítás class Ijsql page 2 extends java.awtPanel implements java.awteventActionListener { /* / public void cb 3 actionPerformed( java.awteventActionEvent event ) { parentForm.SQLStatement = texta sqlgetText(); try { Class.forName(
parentFormdriver); Connection conn = DriverManager.getConnection( parentFormurl, parentForm.uname, parentFormpwd); Statement stmt = conn.createStatement(); stmt.setMaxRows(1); ResultSet rs = stmt.executeQuery( parentFormSQLStatement); textf 6.setText("Rendben A lekérdezés futtatható!"); rs.close(); conn.close(); }catch(SQLException e){ textf 6.setText( "Hiba: "egetMessage()); }catch(ClassNotFoundException c){ textf 6.setText("Nincs ilyen meghajtó: "+ parentFormdriver); } } /* / } A kódrészletben a lekérdezés tesztelése van megvalósítva, melyben egy egyrekordból álló eredményhalmazt kérünk le mindössze azzal a céllal hogy kiderüljön, hogy a lekérdezés szintaktikailag megfelelő-e. Ha nem az akkor kivétel váltódik ki . 79 Internetes adatbázis- kezelés B/3 A lekérdezés tábláinak és mezőinek a meghatározása Táblák kiválasztása class Edit page 1 extends java.awtPanel implements
java.awteventComponentListener, javaawteventActionListener {/* / public void init(){ ResultSet rs = md.getTables(null,null,null,null); while (rs.next()){ lb alltable.addItem( rsgetString(3) ); } } public void page 1 componentHidden( java.awteventComponentEvent event ){ parentForm. tables = lb tablesgetItems(); } public void cb 1 actionPerformed( java.awteventActionEvent event ){ lb tables.addItem( lb alltablegetSelectedItem() ); lb alltable.delItem( lb alltablegetSelectedIndex() ); } public void cb 2 actionPerformed( java.awteventActionEvent event ){ lb alltable.addItem( lb tablesgetSelectedItem() ); lb tables.delItem( lb tablesgetSelectedIndex() ); } DatabaseMetaData md; /* / } Az init metódusban töltjük fel a listát az adatbázis tábláival, a cb 1 és a cb 2 a listák tartalmának alakítására való. Végül amikor elhagyjuk a lapot mindig frissítjük a táblalistát ami az Ijsql applet osztály tagváltozója. . 80 Internetes adatbázis- kezelés Mezők
kiválasztása class Edit page 2 extends java.awtPanel implements java.awteventComponentListener, javaawteventActionListener, java.awteventItemListener{ /* / public void cb 4 actionPerformed( java.awteventActionEvent event ) { String tablaNev = choice tables.getSelectedItem(); String oszlopNev = lb tCols.getSelectedItem(); if (!oszlopNev.equals(null)) lb cColsaddItem( tablaNev+"."+oszlopNev ); } /* / public void choice tables itemStateChanged( java.awteventItemEvent event ) { String tablaNev = choice tables.getSelectedItem(); lb tCols.clear(); try{ ResultSet rs = parentForm.mdgetColumns(null,null,tablaNev,null); while (rs.next()){ lb tCols.addItem( rsgetString(4) ); } }catch(SQLException e){}; } /* / } A fenti kódrészletben az oszlopok kiválasztása és elhelyezése a másik listában látható (cb 4 actionPerformed()). A másik metódus azt mutatja hogy az oszlopok választása előtt egy choice listából ki kell választanunk egy táblát aminek következtében a
választható oszlopok listája frissül, ugyanis lekérdezzük az ehhez a táblához tartozó oszlopneveket. . 81 Internetes adatbázis- kezelés B/4 Szűrőfeltétel megadása class Edit page 4 extends java.awtPanel implements java.awteventComponentListener, javaawteventActionListener, java.awteventItemListener{ /* / public void cb add actionPerformed( java.awteventActionEvent event ) { String uj = textf where.getText(); textf where.setText( "" ); texta where.appendText( uj ); } public void cb and actionPerformed( java.awteventActionEvent event ){ int start = texta where.getSelectionStart(); int end = texta where.getSelectionEnd(); texta where.replaceText( " AND ", start, end ); } public void choice cols itemStateChanged( java.awteventItemEvent event ){ String text = choice cols.getSelectedItem(); String regi = textf where.getText(); int index = textf where.getSelectionStart(); String uj = regi.substring(0,index)+text+regisubstring(index); textf
where.setText(uj); } /* / } A fenti kódrészletben látható hogy hogyan bóvíthetjük a where záradékot újabb elemekkel (cb add), hogyan szúrhatunk be előre elkészített szövegelemeket. A choice cols itemStateChanged metódus arra való hogy a choice-ból való választással szúrhassunk be oszlopneveket a where záradékunkba. . 82 Internetes adatbázis- kezelés B/5 Csoportosító oszlopok meghatározása class Edit page 5 extends java.awtPanel implements java.awteventComponentListener, javaawteventActionListener{ public void page 5 componentHidden( java.awteventComponentEvent event ){ parentForm. groupColumns = lb gbColsgetItems(); } public void page 5 componentShown( java.awteventComponentEvent event ) { lb gCols.clear(); for (int i=0;i< parentForm. columnslength;i++) lb gCols.addItem( parentForm columns[i] ); } public void cb 15 actionPerformed( java.awteventActionEvent event ) { String oszlopNev = lb gCols.getSelectedItem(); if
(!oszlopNev.equals(null)) lb gbColsaddItem( oszlopNev ); } public void cb 16 actionPerformed( java.awteventActionEvent event ){ lb gbCols.delItem( lb gbColsgetSelectedIndex() ); } } . 83 Internetes adatbázis- kezelés B/6 Rendező oszlopok kijelölése class Edit page 3 extends java.awtPanel implements java.awteventComponentListener, javaawteventItemListener, java.awteventActionListener{ /* / public void lb oCols itemStateChanged( java.awteventItemEvent event ){ String item = lb oCols.getSelectedItem(); if (item.endsWith(" DESC")) checkbox descsetState( true ); else checkbox asc.setState( true ); } /* / public void checkbox desc itemStateChanged( java.awteventItemEvent event ){ String item = lb oCols.getSelectedItem(); int index = lb oCols.getSelectedIndex(); if (!item.endsWith(" DESC")) lb oCols.replaceItem( item+" DESC",index ); } public void checkbox asc itemStateChanged( java.awteventItemEvent event ){ String item = lb
oCols.getSelectedItem(); int index = lb oCols.getSelectedIndex(); if (item.endsWith(" DESC")) lb oColsreplaceItem( item.substring(0,itemindexOf(" DESC")), index );; } /* / } Természetesen ebben az osztályban is megvannak az előzőeknek megfelelő metódusok. A fennti kódrészletekben azt láthatjuk, hogy hogyan sikerült a növekvő illetve csökkenő sorrendű lekérdezés problémáját. . 84 Internetes adatbázis- kezelés B/7 A SELECT mondat összeállítása public class SQLSelect extends Object { public SQLSelect(){ } public SQLSelect(String[] tables,String[] columns,String[] order,String where,String[] group){ this.tables=tables; this.columns=columns; this.order = order; this.where = where; this.group = group; } public String[] getTables(){ return tables; } public String[] getColumns(){ return columns; } public String[] getOrder(){ return order; } public String getWhere(){ return where; } public String[] getGroupBy(){ return group; } public void
setTables(String[] tab){ tables = tab; } . 85 Internetes adatbázis- kezelés public void setColumns(String[] col){ columns = col; } public void setOrder(String[] ord){ order = ord; } public void setWhere(String wh){ where = wh; } public void setGroupBy(String[] gb){ group = gb; } public String getSQLSelect(){ StringBuffer buf = new StringBuffer("SELECT "); int i; for (i=0;i<columns.length;i++) { buf.append(columns[i]); if (i<columns.length-1) bufappend(","); else buf.append(" "+ ); } buf.append("FROM "); for (i=0;i<tables.length;i++) { buf.append(tables[i]); if (i<tables.length-1) bufappend(","); else buf.append(" "+ ); } if (!where.equals(null)) { buf.append("WHERE "); buf.append(where+" "+ ); } if (group.length>0) { buf.append("GROUP BY "); for (i=0;i<group.length;i++) { buf.append(group[i]); . 86 Internetes adatbázis- kezelés if (i<group.length-1)
bufappend(","); else buf.append(" "+ ); } } if (order.length>0) { buf.append("ORDER BY "); for (i=0;i<order.length;i++) { buf.append(order[i]); if (i<order.length-1) bufappend(","); else buf.append(" "+ ); } } return buf.toString(); } // adattagok private String[] tables; private String[] columns; private String[] order = null; private String where = null; private String[] group = null; } Az SQLSelect osztály egy select mondatot jelképez. A set/get metódusok a Java konvencióknak megfelelően a select mondat egy-egy jellemzőjét állítják be illetve ezek segítségével kérdezhetjük le azokat. A getSQLSelect metódus pedig az elkészült select mondatot adja vissza nekünk. . 87 Internetes adatbázis- kezelés B/8 Listázás import java.sql*; public class ListResult extends Object { public ListResult(ResultSet rs)throws SQLException{ this.rs = rs; initRS(); } private void initRS()throws SQLException{
ResultSetMetaData rd = rs.getMetaData(); colCnt = rd.getColumnCount(); colWeight = new int[colCnt]; colLabels = new String[colCnt]; for(int i=0;i<colCnt;i++){ colWeight[i]=rd.getColumnDisplaySize(i+1); colLabels[i]=rd.getColumnLabel(i+1); } } public String readHeader(){ StringBuffer buf = new StringBuffer(); String current = null; for (int i=0;i<colCnt;i++){ current = colLabels[i]; while (current.length() < colWeight[i]) current = current.concat(" "); buf.append(current); } return buf.toString(); } . 88 Internetes adatbázis- kezelés public String readRecord()throws SQLException{ if (!rs.next()) moreRows = false; StringBuffer buf = new StringBuffer(); String current = null; for (int i=0;i<colCnt;i++){ current = rs.getString(i+1); while (current.length() < colWeight[i]) current = current.concat(" "); buf.append(current); } return buf.toString(); } public boolean isMoreRows(){ return moreRows; } /* adattagok / ResultSet rs; int colCnt; int[]
colWeight; String[] colLabels; boolean moreRows = true; } A ListResult osztály a select mondat eredményeként előálló eredményhalmaz kiértékelésére való. Az initRS metódus vizsgálja meg a lekérdezés különböző paramétereit a ResultSetMetaData segítségével, így pl. hogy hány oszlopból áll a lekérdezés, mik a fejléc mezők, stb A readHeader metódus segítségével kaphatjuk meg a fejléc sztringet míg a readRecord egy sor kiolvasására használható. . 89