Programozás | Java, JSP » Adatbázis-kezelés Java-ban, a JDBC

Alapadatok

Év, oldalszám:2004, 11 oldal
Nyelv:magyar
Letöltések száma:1557
Feltöltve:2005. december 08
Méret:187 KB
Intézmény:-

Csatolmány:-

Letöltés PDF-ben:Kérlek jelentkezz be!

Értékelések

Ezt a doksit egyelőre még senki sem értékelte. Legyél Te az első!


Új értékelés

Tartalmi kivonat

A JDBC elmélet – I. rész A Java nyelv hálózati lehetőségei miatt ideálisan megfelel kliens-szerver architektúrájú adatbázis-kezelő programok létrehozására; a java programok kommunikálni tudnak a legkülönfélébb adatbázisokkal is, tehát segítségével megoldható az ad atbázis-hozzáférés. Ezen kommunikáció lehetőségét a JDBC – Java D ataBase C onnectivity – biztosítja. A JDBC egy programozói interfész (API) SQL – Structured Querry Language - utasítások végrehajtására A JDBC két részből áll: • • • JDBC alap (Core) API: az adatbázis eléréséhez szükséges alapvető típusokat írja le. Ezeket a javasql standard Java csomag tartalmazza. • JDBC standard kiterjesztés (Extension) API: további haladó szintű JDBC típusokat ír le. Ezeket a javax.sql csomag tartalmazza A JDBC API szolgáltatásait három csoportba lehet sorolni: • • • • • • összekapcsolódás relációs adatbázissal SQL utasítások

végrehajtása SQL lekérdezések eredményeinek feldolgozása A JD BC h asználatával a Jav a ad atbázis-kezelő programjaink nemcsak platform függetlenekké hanem még adatbáziskezelőktől függetlenekké is válnak. Két- és háromrétegű adatbázis-elérési modell A JDBC kétféle adatbázis-elérési modellt támogat: a kétrétegű- valamint a háromrétegű modellt. 1) 1) A kétrétegű modell: a p rogram k özvetlenül az ad atbázis-kezelő rendszerrel kommunikál. Maga az adatbázis akár másik gépen is elhelyezkedhet, mint ahol a program fut, az adatforgalom pedig hálózaton keresztül folyik. Ezt az esetet nevezik kliens-szerver konfigurációnak, ahol az adatbázist tároló gép a szerver, a programot futtató gép pedig a kliens. 2) 2) A háromrétegű modell: a program adott protokollon keresztül egy "középső" szolgáltató réteggel kommunikál. Ez a réteg a programtól kapott parancsokat értelmezi és átalakítja, majd továbbítja azokat

az adatbázis-kezelő rendszerhez. A lekérdezési eredményeket a program szintén a szolgáltató rétegen keresztül kapja meg A középső réteg bevezetése lehetővé teszi az adatbázis hozzáférések könnyű ellenőrzését és optimalizálását is. A szolgáltató réteg Java implementációja esetén az adatbázissal JDBC-n keresztül történik a kommunikáció. JDBC meghajtó-programok A JDBC hívások végrehajtásakor mindig fizikailag is fel kell venni a kapcsolatot a használt adatbázissal. Mivel ezen adatbázis akármilyen típusú (azaz az adatbázis-kezelő bármilyen szoftver) lehet, ezért minden adatbázis-kezelő esetén külön biztosítani kell a JDBC hívások megfelelő értelmezését és kiszolgálását. Ezt a feladatot JDBC programok végzik el Egy J DBC m eghajtó-program v alósítja m eg a JD BC h ívásokat e gy ad ott ad atbázistípushoz a D RIVER i nterfészt implementálva. A meghajtó-programok az alábbi négy csoportba sorolhatóak be: •

• • • • • • • JDBC-ODBC áthidaló program + ODBC meghajtó-program JDBC – saját API áthidaló – meghajtó-program JDBC – hálózati protokoll Java meghajtó-program JDBC – saját protokoll Java meghajtó-program Ezek közül platform- és adatbáziskezelő-független a JDBC – hálózati protokoll Java meghajtó-program és a három rétegű adatbázis-kezelési modell, ahol a kiszolgáló réteg adatbázis-kapcsolatát a kétszintű adatbázis-elérési modellnek megfelelő meghajtó-programokkal lehet megvalósítani. JDBC használata Amint azt már említettem, a JDBC API típusait a java.sql és a javaxsql csomagok tartalmazzák, melyek már a JAVA 2 részei, ezért a JDK 1.2-es változata már tartalmazza őket Korábbi verziók esetén külön kellett ezen csomagokat installálni. A JDBC egyik legkecsegtetőbb felhasználói területe a böngészőprogramokkal történő adatlekérdezés és módosítás appletek/szervletek segítségével. Szervletek

esetén csak maga a szervlet használja a JDBC-t adatbázis-elérésre a szerveroldalon, a böngészőprogram dinamikusan generált HTML oldalak, illetve HTML űrlapok formájában olvashatja, illetve módosíthatja az adatokat. Appletek használatakor a felhasználó közvetlenül hozzáférhet az adatbázishoz JDBC-n keresztül. Ennek egyetlen feltétele, hogy a kliens-oldalról elérhető legyen a használt adatbázis meghajtó-program kódja. M ivel eg y hálózati a pplet a lapértelmezés s zerint c sak a kódját t artalmazó g éppel h ozhat l étre h álózati kapcsolatot, ezért csak olyan adatbázissal kommunikálhat, amely u gyanazon a szerveren fut, m int a honnan a z a pplet kódja is letöltésre került. Többrétegű elérési modell esetén csak a kiszolgáló rétegnek kell ugyanazon a gépen lennie, mint az ap plet k ódjának, maga az ad atbázis ak ár m ás g épen i s l ehet, az ap plet m égis képes le sz a zt – a k iszolgáló rétegen – elérni. JDBC

– architektúra Egy applikációban használt osztályok és interfészek, amelyeket a JDBC használ megtalálhatóak a következő ábrán: Egy JD BC al kalmazás e gy v agy t öbb d rivert i s használhat a java.sql csomagból a DriverManager osztály segítségével. A driverek a datbázis specifikusak, t ehát minden a datbázis más meghajtót használ É pp e zért ugyanazon az applikáción belül dolgozhatunk különböző adatbázisokkal, tehát több driverrel is. Szükségünk lehet egy olyan driverre, amely egy távoli gépen található Oracle adatbázissal kommunikál és egy másik driverre, amely a lokális ODBC kapcsolatot képviseli és egy SQL szerverrel kommunikál. Egy applikációban az adatbázissal való kommunikálás a következő lépéseket követeli meg: A DriverManager-től egy adatbázis-specifikus drivert kérünk A specifikus driver létrehozza a kapcsolatot az adatbázissal és egy Connection típusú objektumot ad vissza A Connection típusú

objektum segítségével létrehozunk egy Statement objektumot, amely egy SQL kérést is tartalmaz az adatbázis felé A Statement objektum az eredményeket egy ResultSet objektumban adja vissza Driverek és drivermanager Meghajtó-program kezelése Amint a zt a f entiekben i s l áthattuk e gy J DBC m eghajtó-program valósítja meg a JD BC h ívásokat e gy ad ott adatbázistípuson, ennek segítségével jön létre a fizikai kommunikáció a program és a megfelelő adatbázis között. Egy meghajtó-programnak a Driver interfészt kell implementálnia. Meghajtó-program kiválasztása A felhasználni kívánt meghajtó-program kiválasztása történhet a szükséges meghajtó-program közvetlen megnevezésével vagy automatikusan a DriverManager osztály segítségével. Ez az osztály a megfelelő meghajtóprogram kiválasztását és használatát segíti Nyilvántartja a pillanatnyilag használható összes regisztrált meghajtóprogramot, és az adatbázis-kapcsolat

kérésekor a kívánt típusú adatbázist kezelő meghajtó-programot f ogja a ktiválni Ugyanakkor a meghajtó-programok kapcsolattartási idejét is ellenőriztetni lehet vele, és a hibaüzenetek nyomon követéséért is ő a felelős. Meghajtó-programok regisztrálása A DriverManager osztály kezeli a regisztrált meghajtó-programok listáját. Egy meghajtó-program rendszerint a betöltése u tán automatikusan, st atikus inicializátor segítségével regisztráltatja magát, a DriverManager osztály registerDriver metódusával, ezért a felhasználónak csak a megfelelő meghajtó-program betöltéséről kell gondoskodnia. A betöltést két módszerrel lehet megvalósítani: • • a m eghajtó-program o sztályának di rekt betöltése a Class.forName statikus m etódussal, a mely a paraméterként kapott nevű osztály dinamikus betöltését végzi el Pl: Class.forName (”comsybasejdbcSysDriver”) Class.forName(”sunjdbcodbcJdbcOdbcDriver”) • • a

jdbc.drivers rendszerparaméter beállításával Ezen rendszerparaméter a meghajtó-programok neveinek kettősponttal elválasztott listáját tartalmazza. A DriverManager osztály inicializálásakor automatikusan betölti ezen rendszerparaméterben felsorolt meghajtó-programokat. E két módszer közül az elsőnek a használata javasolt, mivelhogy az appletek nem állíthatnak be rendszerparamétereket, és a DriverManager csak egyszer, az inicializáláskor veszi figyelembe a jdbc.drivers értékét JDBC gyakorlat Ez itt egy kezdőknek (de talán mégse csak nekik.) szóló cikk lesz a JDBC-ről Először az alapokat fogom bemutatni, ehhez k ell eg y J ava D evelopment K it, eg y M ySQL a datbázis-kezelő és egy JDBC driver MySQL-hez, valamint Java é s SQL ismeretek. A JDBC driver beüzemelése nem nehéz, csupán a Java classpath-ba kell beírni a JDBC driver (ami valójában egy JAR fájl) útvonalát (mivel a c lasspath meghatározása szintén alap Java dolog így

erre sem térnék ki). Szóval elméletileg minden kész ahhoz hogy adatbázis eléréssel ruházzuk fel programjainkat. Első feladatunk hogy létrehozzunk egy MySQL táblát. A példa kedvéért csináljunk egy fórumot ami a lokális gépen fog futni. Ehhez az adatbázis tábla: CREATE TABLE forum( id INT UNSIGNED NOT NULL PRIMARY KEY auto increment, user VARCHAR(40) NOT NULL, email VARCHAR(80) NOT NULL, comment TEXT ); Ezután jöhet a lényeg. A JDBC kapcsolat teremtése a MYSQL-el Ehhez először importálni kell a javasql csomagot Ezután p éldányosítani kell a z Driver osztályt hogy h asználni t udjuk, m ajd f el k ell é píteni a kapcsolatot a z adatbázissal. M iután az ad atbázis k apcsolat l étrejött, indíthatjuk a t ranzakciókat az ad atbázis f elé A lapállapotban az adatbázis kapcsolat felépülése után automatikusan elküldi az adatbázisnak az adatokat. Lássuk a példát: //osztály implementációk import java.sql; //Osztály létrehozás stb. .

//Adatbázis példányosítás Class.forName("orggjtmmmysqlDriver")newInstance(); //org.gjtmmmysqlDriver Jáva driver implementáció java.sqlConnection con; // Jáva kapcsolat prezentálása con=DriverManager.getConnection("jdbc:mysql://localhost/forum?”+ „user=user&password=password"); Amint látható az adatbázis kapcsolatot a DriverManager osztály getConnection metódusa építi fel. Az adatbázis kapcsolatot URL formában kell megadni, melynek felépítése a következő: jdbc:adatbázis típusa://adatbázis host[:port]/adatbázis neve?user=név&password= jelszó FIGYELEM! Az adatbázis kapcsolat létrehozása SQLException kivételt okozhat így azt megfelelően kezelni kell. Ehhez létezik más módszer is, tessék utánanézni a Java API-ba. Ezek után (ha minden jól ment), van egy élő adatbázis kapcsolatunk az adatbázis-kezelővel. A következő lépésben csináljunk egy szabvány select lekérdezést majd az eredményt írjuk ki a

szabvány kimenetre. Az ad atbázis u tasítás v égrehajtása h áromféleképpen t örténhet, eh hez h árom i nterfész v an d eklarálva. E zek a következők: – Statement: Egyszerü SQL utasítás végrehajtására képes – PreparedStatement: Olyan utasítások hajthatók végre vele melyeknek bemeneti értéke is van. – CallableStatement: Tárolt, ki és bemeneti értékekkel rendelkező SQL utasítások végrehajtására Lássuk hogy is megy ez: Statement stmt=con.createStatement(); // A Connection intefész createStatment metódusának visszatérési értéke // egy Statement objektum amely a apcsolathoz tartozó végrehajtásért // felelős Statement interfészt adja vissza. ResultSet // result=stmt.executeQuery("SELECT id,user,comment FROM forum"); A // Statement interface három metódust tartalmaz SQL kérések // végrehajtásához. Első (amit a példánál használunk), az executeQuery // metódus, SELECT utasítások végrehajtására szolgál és

ResultSet // típusu objektumot ad vissza. A másik, az UPDATE, INSERT és hasonló // kérések végrehajtása (melyek nem adnak vissza eredményt) // az executeUpdate metódus, ennek visszatérési értéke mindig // 0. Valamint az execute metódus amely akkor használatos ha az SQL // utasítás többfajta eredményt is visszaad. A ResultSet objektum // az eredménytáblát reprezentálja. A next metódus meghívásával // a következő eredménysorra ugrik, amennyiben nincs több eredménysor, // hamis értéket ad vissza. Tehát a kód: int id; String username; String comment; while(result) { // Ahhoz hogy az SQL eredményt Jávában használni tudjuk azt megfelelő // típusra kell hozni, erre a ResultSet osztály beépített metódusokat // tartalmaz. A metódusok az SQL eredménysor által visszaadott értékek // számát vagy nevét várják vissza (a legtöbb metódusból int és // String-et váró változat létezik) id=result.getInt(1); username=result.getString(2);

comment=result.getString(3); //Ezután kiírjuk az értékeket System.outprintln("id="+id+" -> "+username+" -> "+comment); } Eddig egyszerű volt az életünk, nem kellett az SQL kérésbe adatokat bevinni. most megnézzük hogy hogyan zajlana egy bizonyos sor lekérdezése. Mivel itt bemenő adatokat is kezelni kell, preparedStatement interfészt fogjuk használni. String query="SELECT comment FROM forum WHERE id=?"; int id=8; //Hibakezelés try { //PreparedStatement interfész átvétele a kapcsolatból, //és előfordítás PreparedStatement pstmt=conn.preparedStatement(query); } catch(SQLException e) { System.outprintln("SQL Hiba!"); } try { //Beállítjuk az értéket az SQL querynek pstmt.setInt(1,id); // Az első argumentum annak a sorszáma amelyik helyre a queryben // az értéket be akarjuk helyetesíteni, a második argumentum maga // az érték. ResultSet result=pstmt.executeQuery(); // Végrehajtja az előfordított

utasítást // Az eredmény feldolgozása ugyanúgy folyik mint az elöző esetben. }catch(SQLException e) { System.outprintln("SQL Hiba!"); } A lekérdezéseket a felkínált interfészekkel többféleképpen meglehet valósítani, itt csak lehetséges megoldást ismertettem. Mindenkinek jó kódolást A jdbc elmélet II. rész Kapcsolattartás az adatbázissal A program és az adatbázis közötti kapcsolatot a Connection objektum képviseli. Amint azt már említettem egy program egyszerre több kapcsolatot is fenntarthat ugyanazon vagy akár több különböző adatbázissal is. Egy kapcsolat a kiadott SQL utasításokat és azok eredményhalmazát foglalja magába. A jelenlegi meghajtó-programoktól már elvárható, hogy többszálúan valósítsanak meg egy kapcsolatot, vagyis azonos kapcsolaton belül kiadott több SQL utasítás feldolgozásának párhuzamosítása már nem a programozó, hanem a meghajtó-program feladata. Adatbázis URL-ek Az adatbázissal

való kapcsolat létrehozásánál kérdések sorozata merülhet fel: • hol található az interneten az a számítógép, amely az adatbázist tartalmazza? • melyik porton hallgatja az RDBMS a kéréseket? Az Internet ezt a problémát az URL-ek (Uniform Resource Locator) bevezetésével oldotta meg, amelynek a következő a felépítése: protokoll://hostnév:port/útvonal. Az URL tulajdonképpen a hálózati erőforrások egységes azonosítására s zolgál. Egy ad atbázis-URL a z e lérni kívánt a datbázist j elöli ki A z a datbázis-URL-ek szintaxisa a következő: - jdbc:alprotokoll:adatforrás leírása, ahol: • a protokoll neve: jdbc • az alprotokoll nevét a megfelelő meghajtó-program forgalmazója határozza meg, ezért rendszerint megegyezik a forgalmazó nevével. Egyedüli kivétel az odbc alprotokoll, amely ODBC meghajtó-program és a JDBC-ODBC áthidalóprogram használatát írja elő • az ad atforrás l eírása p edig a k ét ad atbázis e

léréséhez s zükséges t ovábbi ad atokat ( pl. ad atbázis n eve é s a hálózat c íme, a felhasználó n eve é s j elszava) t artalmazza. Ez en ad atok m egadásának k onkrét szintaxisát s zintén a meghajtó-program forgalmazója határozza meg. Kapcsolat felvétele A kért adatbázistípushoz tartozó meghajtó-programnak fel kell tudnia ismerni az URL alapján, hogy rá van-e szükség a kijelölt adatbázissal való kommunikáció lebonyolításához. Ha több driver van betöltve a különböző adatbázisok eléréséért akkor feltevődik a kérdés, hogy hogyan válasszuk ki a megfelelő drivert az aktuális csatlakozáshoz. Ez a kérdés a DriverManager osztály segítségével tisztázódik. Az adatbázis-kapcsolat felvételének szokásos menete a DriverManager getConnection metódusának m eghívása, am elynek p aramétere a k ívánt ad atbázis U RL c ím é s esetleg e gy f elhasználó a zonosító é s jelszó. E kkor a DriverManager sorban megnézi, h ogy

a r egisztrált m eghajtóprogramok közül melyik tudja a kapott adatbázis-URL-t feldolgozni Például egy Oracle driver azonnal észlelné, ha egy más adatbázissal akarsz dolgozni és visszautasítaná a kérést. A DriverManager meghívja a connect metódusát az első olyan meghajtó-programnak, amely a kapott adatbázis-URL-t fel tudja dolgozni. A keresés sorrendje a meghajtóprogramok regisztrációs sorrendjével egyezik meg, ahol a jdbcdrivers rendszerparaméterben megadott meghajtóprogramok megelőznek minden közvetlenül regisztrált meghajtó-programot A DriverManager biztonsági okokból egy adott programnak csak olyan meghajtó-program használatát engedélyezi, amely lokális gépen helyezkedik el, vagy ugyanarról a címről kerül letöltésre, mint ahonnan maga a program is. Ugyanakkor a DriverManager megkerülhető, ha közvetlenül a kívánt meghajtó-program connect metódusának direkt meghívásával vesszük fel a kapcsolatot. A kapcsolat létrejöttekor

egy Connection típusú objektum hozódik létre. A Connection tulajdonképpen e gy interfész, amely biztosítja a kérések eljutását az adatbázishoz és a válaszok megérkezését az adatbázistól. Az interfész metódusokat szolgáltat ahhoz, hogy információkat kapjunk az adatbázisról, bezárja az adatbázissal való kapcsolatot és lehallgatja az adatbázistól visszaérkező üzeneteket. Ugyancsak a Connection interfész tartalmazza a createStatement metódust is, amely egy Statement objektumot hoz létre a következő parancs által: Statement stmt = con.createStatement(); Információ a kapcsolatról Egy adott adatbázis minden jellemzőjéről információt a DatabaseMetaData interférsz f elhasználásával le het lekérdezni. A z a datbáziskapcsolat a datbázisát le író o bjektumot a getMetaData metódussal l ehet m egkapni A lekérdezett információk egy része táblázatszerű, ezeket az SQL lekérdező utasítások eredményeit is reprezentáló

eredménytábla – ResultSet – osztály egy példánya fogja tartalmazni. Az információk egy része adott SQL fogalmak adatbázis-specifikus megvalósítását/korlátait adják vissza (pl. mi a katalógusszeparátor karakter, vagy egy index maximum hány oszlopból állhat stb.) Az ezeket lekérdező metódusok nevei mindig a get szócskával kezdődnek Az információk másik része pedig azt adja meg, hogy az adott adatbázis képes-e valamilyen művelet végrehajtására (pl. ismeri-e a külső join fogalmát stb.) Ezen metódusok nevei mindig a supports szóval kezdődnek Tranzakciókezelés Egy m ásik fontos d olog, a mi id e t artozik a z a t ranzakciókezelés. E gy t ranzakció S QL utasítások végrehajtásából á ll, melyek eredményét v agy v églegesítjük a z adatbázisban ( a commit metódussal), vagy egyszerűen visszavonjuk minden változtatását (a rollback metódussal), visszaállítva ezzel az adatbázis eredeti állapotát. Így a tranzakció addig t

art, a míg le n em zárjuk a commit vagy a rollback metódusok v alamelyikét. Ez után au tomatikusan megkezdődik a következő tranzakció. Egy új adatbázis-kapcsolat alapértelmezés szerint automatikusan nyugtázási móddal jön létre, azaz minden SQL utasítás befejeződése után automatikusan meghívódik a commit metódus. Egy rollback-el az utolsó commit-ig tudjuk visszacsinálni a dolgokat. Egy SQL utasítás akkor fejeződik be, ha teljesen végrehajtódott és nem ad vissza eredményt, v agy h a a z S QL u tasítást ta rtalmazó S QL o bjektumot ú jra v égrehajtjuk. Er edménytáblát v isszaadó S QL utasítás pedig akkor fejeződik be, ha már az eredmény utolsó sorát is feldolgoztuk, vagy ha az eredménytáblát (ResultSet) egyszerűen lezárjuk. Ha az automatikus nyugtázási módot kikapcsoljuk (a setAutoCommit metódussal), akkor a programnak magának kell vezérelnie a tranzakció-kezelést a commit és a rollback metódusok segítségével.

Tranzakció izolációs szintek Egy t öbbfelhasználós ad atbázis-kezelő rendszer esetén előfordulhat, hogy az egyidejűleg futó tranzakciók valamilyen módon zavarják egymást. Például, ha az egyik tranzakció olyan értéket akar olvasni, amit egy másik tranzakció megváltoztatott, d e m ég n em v églegesített, a kkor m ilyen ér téket a djon v issza a z a datbázis? I lyen és eh hez h asonló konfliktusok m egoldására szolgálnak a t ranzakció-izolációs sz intek, m elyek t ulajdonképpen a zt sz abályozzák, h ogy a z adatbázis hogy viselkedjen hasonló problémák fellépésekor. A Connection interfész öt ilyen tranzakció-izolációs szintet definiál: • TRANZACTION-NONE – nincs tranzakciókezelés • TRANZACTION-READ-UNCOMMITED – olvasáskor mindig az aktuális értéket kapjuk • TRANZACTION-READ-COMMITED – olvasáskor csak a véglegesített adatokat kapjuk • TRANZACTION-REPEATABLE-READ – a tranzakció ideje alatt az általa

olvasott értékek más véglegesített tranzakciók esetleges módosító hatása ellenére is mindig megegyeznek a tranzakció kezdetekor érvényben lévő értékekkel • TRANZACTION-SERIALIZABLE – a t ranzakció i deje al att az ál tala o lvasott é rtékeket m ás t ranzakciók nem írhatják felül A fenti sorrend megegyezik a szintek sorrendjével, ahol az első a legalacsonyabb tranzakció-izolációs szint. Minél magasabb a szint, an nál lassúbb lesz az S QL v égrehajtása, mivel az adatbázis-kezelő rendszernek annál több s zinteket a adminisztrációt kell elvégeznie minden művelet v égrehajtása s orán. E zeket a setTranzactionIzolation metódussal lehet beállítani. A szint megváltoztatása tranzakció során nem ajánlott, mivel a változtatás előbb automatikusan véglegesíti az aktuális tranzakciót, csak utána változik meg valójában az izolációs szint. Hibakezelés Elhagyhatatlan dolog a hibakezelés. Ha az adatbázis kapcsolat során

bármilyen hiba történne, akkor egy SQLException kivétel fog kiváltódni. Ez a kivétel a fellépett hibákról a következő információkat tartalmazza: • hiba szövegét, melyet a getMessage metódussal lehet lekérdezni • az X/OPEN SQLstate konvencióban meghatározott SQLstate szöveget • a hiba kódját. Ez meghajtó-program függő és rendszerint az adatbázis által visszaadott hibakódnak felel meg • hivatkozást a következő SQLException-ra. E zzel l ehet a z a ktuális hibaüzenetekhez hozzárendelt e setleges kiegészítő információkat kezelni Az előforduló figyelmeztetések lekezelését az SQLWarning kivételosztály v égzi. Ilyen kivételek nem s zakítják m eg a program futását, mert a megfelelő metódusok maguk elkapják és az aktuális objektumhoz láncolják azokat. A fellépő figyelmeztetéseket a getWarnings metódussal le het le kérdezni, m íg a clearWarnings metódussal le het t örölni. Lekérdezéskor mindig az első

figyelmeztető üzenetet kapjuk ehhez láncba van felfűzve a többi üzenet. A kapcsolat lezárása A kapcsolat lezárása a close metódus használatával történik. A close metódus felszabadítja az adatbázis-kapcsolat által lefoglalt JDBC erőforrásokat. Ez a metódus a kapcsolatobjektum megsemmisítésekor é s b izonyos fatális h ibák fellépésekor automatikusan is meghívódik. A JDBC elm élete - I I I . rész: SQL utasítások végrehajtása Mivel a JDBC adatbázisfüggetlen API, ezért tudnia kell kezelni az adatbáziskezelő rendszerek SQL megvalósításai közötti apró különbségeket is. Ezen probléma megoldására a JDBC három módszert is biztosít: - akármilyen szöveges utasítás (tehát nemcsak SQL utasítások!) átadható az adatbázisnak. Igy egy adott adatbázistípus esetén maximálisan ki lehet használni annak minden specifikus - - lehetőségeit is. A módszer hátránya, hogy a program elveszti hordozhatóságát, mivel nem biztos,

hogy más adatbázis-kezelő is rendelkezik a felhasznált specifikus funkciókkal úgynevezett escape-szintaxis használata. Az SQL escape-szintaxis azt jelzi a meghajtóprogramnak, hogy a benne foglalt kódot másképp kell értelmezni. Az escapeszekvencia mindig kapcsos zárójelpár között áll, és a szintaxisa: { kulcsszó paraméter } , ahol a kulcsszó az escape-szekvencia fajtáját jelzi az adott adatbáziskezelő-rendszer képességeinek lekérdezése a DatabaseMetaData interfész felhasználásával Az SQL utasításokat a következő három interfész segítségével lehet végrehajtani: • Statement: egyszerű SQL utasítások végrehajtására használható • PreparedStatement: bemenő paraméterekkel is rendelkező SQL utasítások végrehajtására lehet használni • CallableStatement: ki/bemenő paraméterekkel is rendelkező tárolt SQL eljárások végrehajtására használható [2] Az egyes fontosabb JDBC osztályokat és kapcsolatukat a következő ábra

szemlélteti: Az itt ábrázolt osztályok segítségével a felhasznált adatbázisok szerkezetének ismeretében a leggyakoribb műveletek könnyen végrehajthatók, de a JDBC definiál az adatbázisok szerkezetének - például táblái nevének, az oszlopai nevének és típusának -, működési paramétereinek megállapítására szolgáló osztályokat is. A Statem ent interfész A Statement interfész tartalmazza az SQL utasítások végrehajtásához és a visszaadott eredmények feldolgozásához szükséges alapmetódusokat. a.) Statement létrehozása Egy fennálló kapcsolatot reprezentáló Connection objektum createStatement metódusával hozható létre egy Statement objektum. Az SQL utasítást azonban nem az objektumok létrehozó, hanem az azt végrehajtó egyik metódusnak kell megadni. Statement stmt = con.createStatement(); b.) Statement végrehajtása A Statement interfész legfontosabb metódusai: • executeQuerry: a paraméterben megadott SQL utasítást

végrehajtja és egy annak eredményét reprezentáló eredménytábla (ResultSet) objektumot ad vissza. Lekérdező SQL utasítások (SELECT) végrehajtásakor használható • • executeUpdate: a paraméterként megadott SQL utasítást végrehajtja és a megváltoztatott adatbázistábla-sorok számát adja vissza. Adatmanipulációs – insert, update, delete – és adatdefiníciós – create/drop table – SQL utasítások végrehajtására használható. Adatdefiniciós SQL utasítások végrehajtása esetén a visszaadott érték mindig 0. execute: ez a metódus is a paraméterében megadott SQL utasítást hajtja végre, de a két előző metódus általánosításának tekinthető. Akkor lehet használni, ha az SQL utasítás egyszerre többfajta eredményt is visszaadhat (pl. tárolt eljárások esetén), vagy nem ismert, hogy milyen típusú a visszaadott eredmény (pl. ismeretlen SQL utasítás dinamikus végrehajtásához). Egy visszaadott eredménytáblát a

getResultSet, adatmanipulációs utasítások megváltoztatott sorok számát a getUpdateCount metódussal lehet megkapni. esetén a c.) Statement befejeződése Az SQL utasítás végrehajtását csak akkor nevezzük befejezettnek, ha nnak végrehajtása után az összes visszaadott eredménykomponens fel lett dolgozva. Egy Statement objektum végrehajtásakor ugyanazon objektum esetleges korábbi végrehajtása által visszakapott eredménytábla automatikusan lezárul. Ez azt jelenti, hogy egy SQL utasítás újbóli végrehajtása előtt mindig teljesen fel kell dolgozni az előző végrehajtásból származó esetleges eredménytáblá(ka)t. Eredm énytáblák kezelése A ResultSet szintén egy interfész. A ResultSet objektum tartalmazza a lekérdezés eredményét, a táblázat első sorától kezdődően. Ez azért kényelmes számunkra, mert egyetlen while ciklussal végig tudunk menni az egész eredménytáblán. Pl: Connection con = DriverManager.getConnection(url,

“azonosító”, “jelszó”); Statement stmt = con.createStatement(); stmt.execute(“SQL-utasítás”); int rowCount; while (true) {rowCount=stmt.getUpdateCount() if (rowCount>=0) { System.outprintln(rowCount + “változott”); stmt.getMoreResults(); continue; } ResultSet rs=stmt.getResultSet(); if (rs!=null) { stmt.getMoreResults(); continue; } break; } Amint láthattuk a ResultSet az eredménytábla soronként történő elérését, az aktuális sor megfelelő oszlopában levő értékek kezelését teszi lehetővé. A JDBC 20 már lehetővé teszi az eredménytáblák tetszőleges sorrendben történő feldolgozását, sőt az eredményeket nemcsak beolvasni, hanem akár módosítani is lehet. Egy eredménytábla típusát két szempont szerint csoportosíthatjuk: - Lehetséges navigálási irány a táblán belül: • TYPE-FORWARD-ONLY: eredménytábla kurzora csak eléfelé mozoghat • TYPE-SCROLL-INSENSITIVE: eredménytábla kurzora mindkét irányba mozoghat, de

nem érzékeli a mások által végzett esetleges módosításokat • TYPE-SCROLL-SENSITIVE: az eredménytábla kurzora mindkét irányba mozoghat, és érzékeli a mások által végzett esetleges módosításokat is - Tábla tartalom módosíthatóság: • • CONCUR-READ-ONLY: az eredménytábla tartalma nem változtatható meg CONCUR-UPDATEBLE: az eredménytábla tartalma megváltoztatható Eredménytáblát a Statement executeQuery és a getResultSet, valamint a DatabaseMetaData különböző információ-lekérdező metódusai adnak vissza. Az eredménytáblának mindig csak egy sora, az aktuális érhető el. Ezt a sort egy külön SQL kurzor jelöli meg Ez a kurzor kezdetben az eredménytábla első sora elé mutat, mozgatni pedig a következő metódusok valamelyikével lehet: next, previous, last, first, afterLast, beforeLast, absolute, relative. Az utolsó két metódus kivételével mindenik jelentése magától érthető. Az absolute metódus a kurzort az adott

számú sorra próbálja pozicionálni, a relative pedig az aktuális pozicióhoz képest relatívan elmozgatni. Az aktuális sor adott oszlopában álló értéket a gettípusnév alakú metódusokkal lehet lekérdezni. Egy oszlopra annak sorszámával vagy nevével is hivatkozni lehet. Egy eredménytábla oszlopairól információt a ResultMetaData interfész felhasználásával lehet lekérdezni, az oszlopokat leíró objektumot pedig a getMetaData metódussal lehet megkapni. Egy eredménytábla lezárásával nem kell a programozónak foglalkoznia – bár megteheti ezt a close metódus segítségével -, az automatikusan megtörténik, ha a táblát létrehozó Statement lezáródik, újra végrehajtásra kerül, vagy elkezdődik a következő visszaadott eredménykomponensének a feldolgozása. A P reparedStatem ent interfész Adatbázis-alkalmazásokban gyakori eset, hogy ugyanazt az utasítást kell többször vegrehajtani. Egy metódus kezelhet egy információtömböt és

beszúrhatja az egyes elemeket egy adatbázisba, vagy fogadhat sok különböző nevet vagy más azonosítót és visszaadhatja egy lekérdezés eredményeit egy vektor minden elemére. Szerencsére a legtöbb RDBMS támogatja a preparált utasításokat, melyeket egyszer kell létrehozni, elemezni és optimizálni az adatbázisban, majd újra meg újra használni az alkalmazásban. A JDBC támogatja a preparált utasításokat a Statement osztály PreparedStatement alosztályával. Tehát a PreparedStatement interfész a Statement kiterjesztettje. Abban különbözik tőle, hogy ennek egy példánya már tartalmaz egy sql utasítást, és hogy ez az sql utasítás tartalmazhat bemenő paramétereket is. Az utasítás végrehajtása előtt minden bemenő paraméternek értéket kell adni a megfelelő set metódusok valamelyikével. Mivel ez az SQL utasítástípus előfordított, ezért gyorsabb a végrehajtás, mint a Statement objektumok esetén. Tehát az egyik nagy különbség a

Statement és a PreparedStatement között az, hogy a PreparedStatement konstruktora argumentumként egy SQL utasítást vesz át. Ezáltal a konstruktor az adatbázisban csak egyszer hozza létre a lekérdezést A másik különbség az SQL-ben lévő kérdőjelek. Eltérően a szabályos Statement-től, amely minden alkalommal újból keletkezik végrehajtás előtt, a PreparedStatement változatlanul tárolódik a kódon belül. Ha nem lenne mód a PreparedStatement paramétereinek megváltoztatására, valahányszor végrehajtódik, az egész ötlet haszontalan lenne. Itt jönnekbe a kérdőjelek Minden kérdőjel egy paraméter helyén áll, amely a lekérdezés végrehajtása előtt beállítható. Az adatbázis ezeket paraméterekkel helyettesíti be, mielőtt végrehajtja a prekompilált lekérdezést. A PreparedStatement nemcsak hatékonyabban van implementálva sok adatbázisban, de sokkal könnyebben használható is a programon belül. Létrehozása a fennálló kapcsolatot

képviselő Connection objektum prepareStatement metódusával történik. Az előfordított SQL utasítás létrehozásához maga az utasítás egyből átadódik az adatbázisnak. Pl: prepareStatement(”UPDATE tábla SET oszl1=? WHERE oszl2=?”) Végrehajtás előtt minden bemenő paraméternek be kell állítani az aktuális értékét. A végrehajtó metódusokat paraméter nélkül kell meghívni, különben SQLException-t fognak kiváltani. Egy bemenő paraméter értékét a settípusnév metódusokkal lehet beállítani, a NULL érték pedig a setNULL metódussal állítható be. A CallableStatem ent interfész A CallableStatement interfész a PreparedStatement kiterjesztettje. Tárolt SQL eljárások meghívására lehet használni. Egy tárolt eljárás hívása a bemenő paramétereken kívül kimenő paramétereket is használhat. Egy paraméter egyszerre lehet kimenő és bemenő paraméter is Létrehozása a Connection objektum prepareCall metódusával történik.

Az eljárás meghívása az escape-szintaxis segítségével történik: • {call eljárásnév [(?,?,)]} – visszatérési érték nélküli tárolt eljárás hívása • { ?= call eljárásnév[(?, ?, )]} – visszatérési értékkel rendelkező tárolt eljárás hívása Végrehajtás előtt be kell állítani a bemenő paraméterek aktuális értékét és minden kimenő paraméternek meg kell adni a típusát a registerOutParameter metódus segítségével. Egy kimenő paraméter értékét a gettípusnév alakú metódusokkal lehet lekérdezni. Javasolt, hogy a maximális hordozhatóság érdekében a kimenő paraméterek értékét csak minden visszaadott eredménykomponens feldolgozása után kérdezzük le.[2]