1.

INTRODUCERE In sistemele de gestiune a bibliotecilor
Evidenţierea extraordinarelor schimbări introduse de tehnicile de informare în biblioteci şi centrele de documentare, începând cu anii 1960, este fără îndoială un loc comun. Toţi aceşti ani de adaptare, de experimentare, de utilizare a unor noi tehnici, noi echipamente sau noi documente au modificat considerabil, profund şi iremediabil nu numai peisajul instituţiilor, ci în egală măsură deprinderile de lucru ale profesiei. Semnificativ e că s-a simţit nevoia unei noi terminologii pentru desemnarea unor „biblioteci" ale căror colecţii nu mai erau alcătuite doar din cărţi. In plus, o bibliotecă din zilele noastre, loc de cultură deschis asupra lumii înconjurătoare, nu poate ignora mutaţia de fond la care asistăm în prezent. Introducerea de noi documente e însoţită de aceea de noi echipamente, a căror formă elementară poate fi un simplu aparat de lectură, dar cea mai elaborată, calculatorul, aduce o totală revoluţionare a organizării interne a instituţiei. În afara aspectului uman, fără de care nu există bibliotecar, nici utilizator, rapidele progrese tehnice ale informaticii în lumea informării documentare, dezvoltarea reţelelor, apariţia inovatoare a unor noi suporturi de informaţie, nevoia de a lucra în colaborare sau întărirea schimburilor bibliografice implică, în general, necesitatea unei informatizări a bibliotecii ori a centrului de documentare.

1.1.Istoricul şi evoluţia programelor de gestionare a bibliotecilor Informatica a devenit atât de importantă în zilele noastre deoarece ea este, de departe, cel mai puternic instrument de prelucrare a informaţiei conceput vreodată de om. Ea îşi arată pe deplin măsura ca instrument privilegiat de prelucrare în sistemele de informare, mai ales în domeniul documentării ce manipulează astăzi cantităţi uriaşe de date a căror valoare economică este, şi ea uriașa. Moore a făcut o previziune a semiconductorilor pe 19 aprilie 1965, când a spus ca numărul de tranzistori dintr-un chip se va dubla la fiecare 2 ani favorizând răspândirea computerelor peste tot in lume, si de asemenea, costurile de producție vor scade din ce in ce mai mult. Previziunea lui Moore s-a dovedit perfect adevărata, un Quad Core Extreme Edition pe 1

45nm având in prezent peste 820 de milioane de tranzistori. De asemenea, raportându-ne la costurile de fabricație, un tranzistor dintr-un procesor Intel actual costa de un milion de ori mai puțin decât unul inclus intr-un chip construit in 1971.Daca mașinile ar fi evoluat la fel, acum am fi putut cumpăra un autovehicul cu...un cent. Jaloane istorice In secolul al IX-lea, Al-Khowarisni, matematician din Bagdad, scrie un manual de aritmetică bazat pe numerotarea poziţiei. De la numele său provine termenul „algoritm". Secolul al XVII-lea este deosebit de fertil în invenţii: în 1623, germanul Schickard realizează o maşină de calcul; în 1648, Pascal inventează şi el o maşină de calculat, iar Leibniz creează în 1673 o maşină de înmulţit. Vaucanson, mai cunoscut pentru calitatea şi finisajul automatelor sale, se va afla, în anii 1750, la originea unui prim război de ţesut automat, perfecţionat de Jacquard către sfârșitul secolului al XVIII-lea, devenind astfel, poate, prima maşină funcționând cu ajutorul cartelelor perforate. In secolul al XlX-lea, Babbage lucrează la realizarea unor maşini care să funcţioneze pe principiile calculatoarelor. Boole îşi publică analiza matematică a logicii în 1847, în timp ce Cebîşev inventează în 1881 o maşină capabilă să efectueze adunări şi înmulţiri. In 1880, în Statele Unite, Hollerith „inventează" cartela perforată şi concepe două procedee pentru a o citi: unul, mecanic, inspirat de războaiele de ţesut ale lui Jacquard, foloseşte două tije metalice care străbat fişele prin găurile perforate, altul, electric, în care vidul lăsat de perforaţii stabileşte trecerea unui curent. Hollerith îşi va completa progresiv sistemul cu o maşină de perforat, o maşină de triat capabilă să citească cartelele şi să le dirijeze spre compartimentele de clasare şi, în fine, o maşină tabulatoare capabilă să citească şi să socotească. Invenţiile lui Hollerith nu vor avea nici un succes până la crearea lui Tabulating Machine Corporation ce va deveni mai târziu International Business Machine, cunoscută azi sub denumirea de IBM. In 1900, Torres Quevedo realizează o maşină în stare să rezolve ecuaţii folosind reprezentări ale numerelor prin virgulă flotantă. în 1930, Louis Couffignal descrie o nouă maşină de calculat şi subliniază, într-o comunicare la Academia de Ştiinţe, din 1936, importanţa folosirii reprezentării binare în funcţionarea maşinilor. Abia în 1940 se face cu adevărat intrarea în era informatică, atunci când IBM depune brevetul unui totalizator electronic, în conceperea căruia n-au mai intrat dispozitive mecanice. 2

1.2.Istoria informatizării bibliotecilor Utilizarea calculatorului „Istoria" Informatizării bibliotecilor începe cu adevărat in mijlocul anilor 1950 când primele calculatoare si-au făcut apariţia In mediile universitare din Statele Unite. Pe atunci era vorba de calculatoarele din "prima generație" de o concepţie identica cu aceea a posturilor de radio „cu lămpi", pe baza de tuburi electronice legate intre ele prin fire cablate manual si folosind cartele perforate , apoi benzi magnetice. Mărimea lor o depăşea cu mult pe aceea a fişierelor manuale ale unei biblioteci mijlocii, necesitau prezenţa constantă a unei echipe de informaticieni, iar capacităţile lor în materie de prelucrare documentară erau mai mult decât limitate, căci tehnologia în evoluţie nu le permitea să îndeplinească decât prelucrări ulterioare; aceste maşini costisitoare, complexe, lente şi greu de manevrat, erau mai mult calculatoare decât maşini capabile să prelucreze un text. Anii 1960 In istoria informaticii, aceasta e perioada marilor descoperiri, fie că e vorba de progresele dobândite cu ajutorul diferitelor echipamente, fie de apariţia reţetelor şi a serverelor de date. Apariţia formatului MARC După experimentarea sa între 1966 şi 1968 de către Biblioteca Congresului şi de alte şaisprezece biblioteci din Statele Unite, inovaţia s-a răspândit foarte repede pe tot teritoriul Statelor Unite, luându-se în considerare o situaţie la scară naţională cu totul specifică şi necunoscută în Franţa : bibliotecile nord-americane, fie ele publice, universitare sau de cercetare, obişnuiau deja să-şi procure fişele noilor achiziţii de la Biblioteca Congresului, reducând astfel considerabil timpul consacrat catalogării locale : într-adevăr, aceste fişe cuprindeau nu numai o descriere bibliografică standardizată, ci şi în afara cotei Bibliotecii Congresului, o indexare pe materii conform Library of Congress Subject Headings (LCSH) şi un indice Dewey. Din 1967, Biblioteca Congresului a publicat o a doua versiune a formatului său, botezată MARC II, ulterior denumită USMARC, concepută în mod mai specific pentru facilitarea schimbului de notiţe bibliografice, Trecerea la o nouă structurare a datelor nu a declanşat fenomenul de respingere şi

3

formatul MARC a devenit curând un standard naţional care permitea fiecărei biblioteci să primească o bandă magnetică săptămânală. Atenţia s-a îndreptat rapid către reţelele specializate în transportul datelor în pachete ce ofereau pentru prima oară posibilitatea de tranzacţii interactive ; astfel începea era lucrului „online". Ca un amănunt, ARPANET (Advanced Research Projects Agency Network) a fost, în 1969, prima reţea de transmitere în pachete între principalele organisme de cercetare militară din Statele Unite ; devenit civil, după numeroase dezvoltări tehnice şi o spectaculoasă criză de gigantism, azi e cunoscut sub numele de Internet. Anii 1970 Dintr-un punct de vedere general, am putea aprecia foarte schematic anii 1970 drept o perioadă a „timpului partajat".Atunci se produce marele val seismic ce atinge Franţa din plin. Comercializarea maşinilor de „a patra generaţie" începe o data cu apariţia primului microcalculator construit în jurul microprocesorului inventat în 1970 dar care nu va ajunge în lumea bibliotecilor decât zece ani mai târziu. Totuși performanţele acestui tip de aparat sunt practic echivalente cu cele ale maşinilor din prima generaţie. Pe de altă parte, preţurile sânt în cădere liberă costul unul tranzistor a fost împărţit la 20.000 între 1960-1976... Dar va trebui aşteptat anul 1980 pentru a se saluta apariţia primului microcalculator portabil. Anii 1980 Sunt marcaţi de conştientizarea comunităţii bibliotecarilor francezi în privinţa standardizării şi a folosirii de instrumente comune. Catalogul colectiv naţional al publicaţiilor seriale apare în 1983 din fuziunea dintre IPPEC (Inventarul permanent al periodicelor în curs), AGAPE (Aplicarea gestiunii automatizate la periodice), CPI (Catalog de periodice interregional) şi CIEPS (Centrul internaţional de înregistrare a publicaţiilor seriale). In plus, apare o preocupare faţă de conceptul de catalog colectiv de lucrări (CCO); această idee este aplicată azi de o manieră mai extinsă în Catalogul colectiv al Franţei. Apariţia microcalculatorului în bibliotecă Deceniul 1980 a văzut introducerea primelor microcalculatoare în bibliotecile publice, cel mai adesea fiindcă era instrumentul necesar pentru asigurarea regăsirii notiţelor bibliografice pe un compact disc optic, dar deseori era un echipament dedicat, puţin sau deloc legat la sistemul 4

informatic al bibliotecii; în paralel, microcalculatoarele au fost utilizate pentru lucrări de birou, cel mai adesea total independente de sistemul de gestionare a bibliotecii. La sfârșitul deceniului '80 au apărut softurile de gestionare a bibliotecii, deseori destinate unor mici instituţii. In fine, a fost, din păcate, utilizat pentru „meşterirea", ca în anii 1970, a sistemelor „locale" ; aceste sisteme, construite cu softuri de aplicaţii birotice (Word,- Excel etc.) sau de sisteme de gestionare a bazelor de date (Dbase, Acces, Paradox etc.) nu sunt, din nefericire, viabile în contextul actual: în unele cazuri, se poate că oferă, posibilitatea regăsirii unor date bibliografice, ceea ce ar răspunde unei nevoi precise, dar procesul lor de elaborare dovedeşte că analiza e pe Termen foarte scurt, ceea ce ar avea, cu certitudine, grave consecinţe economice pentru instituţie. Dezvoltarea microinformaticii în anii 1980 a avut şi o altă consecinţă: vechea discuţie ce opune lumea bibliotecilor celei a centrelor de documentare a prilejuit evoluţia unor aplicaţii separate : - Pe de o parte, pachetele de programe zise „documentare", ignorând adesea formatele MARC şi fişierele de autoritate, dar care aveau importante funcţii de indexare pe subiecte, ba chiar de interogare în text; în pofida tuturor calităţilor de putere de căutare, aceste produse devin, in general, total „proprietare", deci incompatibile între ele. - Pe de altă parte, pachetele de programe zise „de bibliotecă", cu o structura mai „rigidă", ştiind în mod normal să administreze la intrare şi în ieşire datele structurate în format MARC şi având funcţi speciale cu, de pildă, un modul de împrumut. Anii 1990 După perioada timpului partajat şi a anilor micro, iată-ne în era lui multimedia, a interactivităţii, a reţelelor interconectate şi a informaticii „de comunicaţii", graţie unei dezvoltări rapide a reţelelor. In 3 ianuarie 1994, din fuziunea dintre Biblioteca Naţională şi Biblioteca Franţei ia naştere Biblioteca Naţională a Franţei, care trece la realizarea unui sistem de informare (SI) foarte ambiţios, total integrat, sprijinit pe conceptele tehnice cele mai moderne şi care va trebui să devină centrul unei vaste reţele naţionale. Pe un plan mai general, primii ani ai deceniului '90 arată o tendinţă de reunificare a activităţii bibliotecilor universitare şi de cercetare şi a bibliotecilor publice : bibliotecile universitare adoptă sistemele integrate, folosind astfel aceleaşi pachete de programe ca bibliotecile publice ; în plus, apare o nouă piaţă : localităţile mici îşi informatizează bibliotecile. Supremaţia furnizorilor francezi demonstrează o tendinţă spre uzură în faţa produselor anglosaxone, formatul MARC şi sistemul de operare UNIX pe minicalculator se impun, dar ambele cu 5

grade foarte diverse de standardizare. De altfel, pachetele de programe „documentare" şi cele „de bibliotecă" arată o tendinţă evoluând spre un tip de pachete de programe unic integrând gestionarea documentului. In zilele noastre, se afirmă tendinţele tehnice; sunt de remarcat mai multe mutaţii importante în curs de desfăşurare : o netă schimbare de destinaţie a sistemelor specifice înspre aplicaţii portabile, o tendinţă de standardizare a sistemelor de gestionare a bazelor de date (SGBD), o remarcabilă deschidere către sistemele integrate de pe piaţa, dezvoltarea rapidă a reţelelor locale datorată, în parte, unei creşteri importante a performanţelor modemelor, o tendinţă încă modestă de standardizare a limbajelor de căutare, apariţia de baze de date distribuite, programarea orientată pe obiect, utilizarea în creştere, a sistemelor de gestionare a bazelor de date relaţionale (SGBDR), indexarea în text integral sau interogarea bazelor de date în limbaj natural. Însă, cea mai importantă tendinţă şi ale cărei consecinţe vor fi foarte puternice în lumea informaticii nu şi-a încheiat încă evoluţia : este vorba de modelul client/server.

2.Activitățile de proiectare a bazei de date

6

Activitățile de proiectare a bazei de date, constituie obiect de studiu pentru doua domenii ale sistemelor informaționale. Este vorba, pe de o parte, de dezvoltarea de aplicații software, iar pe cealaltă parte de un domeniu mai larg care țintește mai mult decât la realizarea de aplicații. Este vorba de analiza si proiectarea sistemelor informaționale. Analiza si proiectarea se ocupă, printre altele si cu investigarea tuturor proceselor, operațiunilor si tranzacțiilor dintr-o firma sau instituție, cerințele utilizatorilor si perspectivelor organizaționale, astfel incit toate aceste aspecte sa fie luate in calcul in realizarea unui sistem informațional coerent, aliniat misiunii, obiectivelor si politicilor firmei. Cu alte cuvinte analiza si proiectarea pornesc mai din amonte , de la utilizatori, procese, tranzacții economice, încercând sa modeleze realitatea sub forma unei largi game de diagrame , scheme, specificații pe care le vor înainta realizatorilor modulelor de interferenta, prelucrări si date. Una dintre cele mai cunoscute scheme de Planificarea aplicațiilor de lucru cu baze de date realizare a BD sau schema de principiu a ciclului de viața al aplicațiilor cu BD este cea din edițiile lucrării lui Thomas Connoly si Carolyn Begg1, prezentata in figura 1.1. Amploarea activităților din ciclul de viața a unei BD depinde de anvergura aplicației. Când sistemul dezvoltat vizeaza un număr redus de utilizatori si se refera la un ansamblu de funcții nu din cale-afara de complex, multe etape sunt sărite sau parcurse sumar. Planificarea BD
cerințelor Colectarea si analiza Definirea sistemului

presupune, eșalonarea pașilor ciclului de viața pentru atingerea unui maxim de eficacitate. Ca si in cazul planificării software-ului, planificarea BD presupune identificarea si evaluarea activităților ce trebuie derulate, resurselor necesare derulări activităților, fondului de timp, specialiștilor si banilor disponibili. Planificarea BD trebuie integrata in strategia de ansamblu a Proiectarea conceptuala firmei, unul dintre obiectivele esențiale fiind catalizarea activităților, politicilor si a strategiei .
SGBD Proiectarea BD Proiectarea logica Selectarea aplicației Proiectarea

Proiectarea fizica

Definirea sistemului Presupune specificarea domeniului si granițelor aplicației ce lucrează cu baza de date,
Prototipizarea Implementarea

utilizatorilor, aplicabilității sale, precum si a celorlalte componente ale sistemului informațional la care se va conecta noul subsistem.
Încărcarea si conversia datelor
1

. Connolly, T., Begg, C.E., Strachan, A.D., Database Systems. A practical Approach to Design, Implementation and
Testarea

Management, Addison-Wesley, Harlow, 1996

7
Întreținerea operaționala

Fig. 1.1 Ciclul de viața al aplicațiilor ce folosesc baze de date Colectarea si analiza cerințelor Aceasta etapa implica adunarea si analiza cerințelor aplicațiilor din partea utilizatorilor. Cerința reprezintă o opțiune, un element ce trebuie inclus, tratat in noul sistem . Proiectarea BD se bazează pe informații despre organizații, informații ce trebuie preluate si gestionate de baza. Acestea pot fi culese in diferite moduri: 8

-

intervievarea personalului din firme, cu precădere a celor mai apropiați, prin

specificul activității lor, de profilul aplicației, avându-se in vedere acordarea unei atenții mărite experților in compartimentele funcționale considerate; utilizatori; Utilizarea experienței acumulate la proiectarea unor sisteme similare. Informația culeasa trebuie sa includă: principalele domenii si grupuri de utilizatori; documentația utilizata sau generata de si despre aceste domenii de utilizatori; detaliile tranzacțiilor reclamate de fiecare domeniu in parte; o lista de cerințe, pe priorități, a fiecărui domeniu . Rezultatul acestei activități îl reprezintă specificațiile cerințelor organizaționale, prezentate de obicei , sub forma unui set de documente in care sunt descrise , din diferite unghiuri, operațiile firmei. Proiectarea bazei de date Aceasta include proiectarea logică şi fizică a BD. În urma acestei etape va fi elaborat modelul BD care va constitui suportul obiectivelor şi operaţiunilor organizaţiei. Principalele obiective ale proiectării BD sunt:
-

Observarea modului de derulare a operațiilor in cadrul firmei; Examinarea documentelor, in principal a celor purtătoare de informații; Folosirea chestionarelor pentru preluarea de informațiilor de la un număr mare de

reprezentarea datelor şi a relaţiilor dintre date, formulare pe diferitele zone ale furnizarea unui model al datelor care să permită orice tranzacţie autorizată asupra construirea unui proiect care va atinge cerinţele de performanţă ale sistemului,

aplicaţiei şi ale grupurilor de utilizatori;
-

acestora;
-

cum ar fi: securitatea, timpul de răspuns etc. Deseori însă, realizarea unui obiectiv se face în detrimentul altuia. Spre exemplu, un nivel ridicat de securitate atrage după sine scăderea vitezei de răspuns. După Connoly şi Begg2, există două abordări majore ale proiectării BD. Abordarea bottom-up porneşte de la nivelul elementar, cel al atributelor, care sunt grupate în clase de entităţi şi asociaţii. Normalizarea este un exemplu tipic de demers bottom-up, care dă rezultate
2

. Connolly, T., Begg, C.E., Database Systems. A practical Approach to Design, Implementation and Management, editia a III-a

Addison-Wesley, Harlow, 2002

9

bune atunci când numărul atributelor nu este prea mare. Când numărul de atribute este ridicat, mai nimerit este abordarea top-down care dezvolta mai întâi un model sintetic, simplificat al datelor. Cele câteva entităţi sunt descompuse ulterior In mai multe etape, până la identificarea atributelor si entităţilor elementare. Modelarea folosind diagrame E-R are la bază abordarea topdown. Selectarea sistemului de gestiune a bazei de date Considerată un pas opţional, selectarea SGBD presupune alegerea celui mai adecvat SGBD pentru realizarea si exploatarea aplicaţiei. Nu toate SGBD-urile satisfac cerinţele aplicaţiei, iar pe de altă parte, cele mai performante sunt şi cele mai scumpe. Cerinţele de funcţionalitate trebuie coroborate cu resursele disponibile, în vederea identificării celui mai adecvat SGBD comercial pentru realizarea si exploatarea aplicaţiei. Proiectarea aplicaţiei Proiectarea aplicaţiei se referă la conceperea secvenţelor de cod (instrucţiuni în limbaje de programare) ce vor lucra cu baza. Din fig.1.1 se observa ca proiectarea BD si proiectarea aplicaţiei sunt activităţi distincte, paralele ale ciclului de viaţă al aplicaţiilor cu BD. În cea mai mare parte a cazurilor, proiectarea aplicaţiei nu poate fi finalizată înainte de proiectarea bazei. Pe de altă parte, informaţiile proiectării vor fi transmise proiectării BD. În această etapă trebuie verificat dacă toate funcţiile specificate în cerinţele utilizatorului se regăsesc în proiectul aplicaţiei. Proiectarea aplicaţiei include şi activitatea de proiectare a tranzacţiilor. De asemenea, tot acum se elaborează şi modelul interfeţei cu utilizatorul a aplicaţiei. Prototipizarea Deşi opţională, prototipizarea se poate dovedi deosebit de utilă prin construirea unui model de lucru iniţial simplificat, model ce permite dezvoltatorilor şi utilizatorilor să testeze şi să amelioreze incremental noua aplicaţie. Un mare avantaj al prototipizării este gradul mult mai mare de acceptare a noului sistem la final, acesta fiind dezvoltat împreună eu utilizatorii ce pot să-şi exprime pe parcurs doleanţele. Etapele prototipizării sunt descrise în fig. 1.23
3

Connolly, T., Begg, C.E., Strachan, A.D., Database Systems. A practical Approach to Design, Implementation and

Management, Addison-Wesley, Harlow, 1996

10

Dezvoltarea modelului de lucru

Abandonarea aplicației Implementarea aplicației Decizie Redezvoltarea aplicației Demararea unui nou prototip

Construirea prototipului

Utilizarea si testarea prototipului

Revizuirea prototipului

Fig. 1.2 Schema de principiu a prototipizării Implementarea Presupune crearea definițiilor BD la nivelurile conceptual, extern si intern, precum si punerea in lucru a aplicației, fiind realizata utilizând limbajul de definire a datelor (DDL) pus la dispoziție de SGBD-ul selectat. Implementarea aplicației se realizează intr-un mediu de programare utilizând un limbaj de tip 3GL sau 4GL. 4GL - fourth-generation programming language - este un limbaj de programare sau mediu de programare proiectat cu un anumit scop, cum ar fi dezvoltarea de software comercial de afaceri. Toate 4GLs sunt concepute pentru a reduce efortul de programare, timpul necesar pentru a dezvolta software-ul, precum şi costurile de dezvoltare software4. Conversia şi încărcarea datelor Acest pas este necesar atunci când aplicaţia dezvoltată înlocuieşte o alta. Datele trebuie transferate din vechea aplicaţie în cea nouă, operaţie ce implică de multe ori schimbarea structurii fişierelor, a formatului, logic şi fizic, al datelor, în concordanţă cu cerinţele noii aplicaţii, dar şi ale noului SGBD. Uneori sunt necesare (şi posibile) şi conversii ale unor programe din vechiul în noul sistem. Majoritatea SGBD-urilor actuale au module de importexport din/în alte SGBD-uri. Conversia aplicaţiilor este, în general, mult mai complexă atunci când se schimbă limbajul/mediul de programare.
4

http://en.wikipedia.org/wiki/4GL

11

Testarea Testarea este operaţiunea sistematică de verificare a funcţionalităţii sistemului, a gradului de adecvare la cerinţele utilizatorilor. Prin testare, aplicaţia este lansată în execuție, urmărindu-se depistarea eventualelor erori şi ameliorarea unor parametri precum viteza, securitatea etc. Urmând o metodologie riguroasă, măsurătorile din cadrul testării dau posibilitatea evaluării calităţii şi fiabilităţii software-ului. Este de preferat ca utilizatorii aplicaţiei să fie pe deplin implicaţi în procesul testării, iar aplicaţia testată să fie instalată pe un alt sistem decât cel pe care a fost concepută; în orice caz, trebuie avut în vedere şi un mecanism de recuperare a datelor corupte în caz de avarie. Există mai multe strategii de testare a corectitudinii şi funcţionalităţii unei aplicaţii de lucru cu BD ce pot fi aplicate individual sau combinate în cadrul aceluiași sistem:
-

top-down; bottom-up; fire de execuție; test de stres.

Testarea top-down Începe de la nivelul superior al funcţiilor majore ale aplicaţiei. Este utilă în verificarea arhitecturii sistemului, reproiectările majore fiind semnalate din primele momente ale testării. Testarea bottom-up începe cu modulele elementare şi continuă pe verticală cu modulele compozite până la nivelul general al aplicaţiei. Testarea firelor de execuţie este foarte importantă în sistemele de prelucrare în timp real, în care sunt rulate simultan o serie de procese ce cooperează. Acest tip de testare este mult mai complex, fiind legat de detaliile tehnice ale sistemului de operare. Fiecărui proces i se alocă un fir de execuţie (thread) care este urmărit de la declanşarea sa, acordându-se o mare importanţă punctelor de întâlnire cu celelalte fire executate pe sistem. Testul de stres presupune suprasolicitarea bazei şi aplicaţiilor. Astfel, BD se încarcă automat cu un număr extrem de mare de înregistrări, iar la aplicaţie se conectează cât mai mulţi utilizatori. Astfel se depistează până la ce limite rezistă aplicaţia. Întreţinerea operațională Această activitate se derulează pe toată durata de utilizare a aplicaţiei. în afară de monitorizarea BD, a programelor, de „curăţarea" periodică şi repararea eventualelor erori 12

hard/soft, tot în această activitate sunt încorporate operaţiunile de actualizare a datelor şi programelor (ca urmare a unor noi oportunităţi tehnologice), modificarea unor parametri (procente TVA, impozite etc.). Monitorizarea performanţei sistemului se realizează prin raportarea la un nivel prestabilit de acceptare. Dacă este cazul, o situare a performanţei generale sub acest punct critic poate antrena reorganizarea BD. Altminteri, chiar şi în cazul funcţionării în parametri normali, BD trebuie optimizată, având în vedere şi facilităţile oferite de SGBD. Întreţinerea şi actualizarea aplicaţiei sunt necesare în mai mare sau mai mică măsură. Spre exemplu, într-un mediu economic şi legislativ dinamic, cum este cel din ţara noastră, deseori este necesară modificarea unor părţi importante ale aplicaţiei. Uneori, modificarea presupune reluarea unora sau tuturor paşilor din ciclul de viaţă al aplicaţiei de lucru cu BD.

3. Studiu asupra proiectării si normalizării unei baze de date
Descrierea unui model de date se bazează, în principal, pe trei elemente: structura - modul în care sunt organizate efectiv datele în bază, integritatea - mecanismul de asigurare a corectitudinii datelor, manipularea - în sensul modificării şi extragerii informaţiilor din bază.

Pentru proiectarea bazei de date, ne interesează primele două aspecte, deşi, vrândnevrând, atunci când ne vom pune problema implementării tuturor restricţiilor bazei în oricare dintre SGBD-uri, vom recurge copios la opţiunile manipulative ale modelului. Modelul relaţional s-a conturat în două articole publicate în 1969 şi 1970 de către E.F. Codd, matematician la centrul de cercetări din San Jose – California, al firmei IBM. In acel moment, tehnologia bazelor de date era centrată pe modelele ierarhic şi reţea, modele ce depind într-o mai mare măsură de organizarea internă a datelor pe suportul de stocare. Codd a propus o structură de date tabelară, independentă de tipul de echipamente şi de software-ul de sistem pe 13

care este implementată,o structură „înzestrată" cu o serie de operatori pentru extragerea datelor. Faţă de modelele ierarhic şi reţea, modelul relaţional prezintă câteva avantaje: său. propune structuri de date uşor de utilizat; ameliorează independenţa logică şi fizică; pune la dispoziţia utilizatorilor limbaje neprocedurale; optimizează accesul la date; îmbunătăţeşte integritatea şi confidenţialitatea datelor; ia in calcul o largă varietate de aplicaţii; abordează metodologic definirea structurii bazei de date.

Există o largă tipologie a SGBDR-urilor, aşa încât orice categorisire îşi are riscul Cele mai accesibile şi, implicit, cele mai utilizate sunt SGBDR-urile dedicate iniţial uzului individual: Access, Paradox, Visual FoxPro. Astăzi, multe dintre acestea au caracteristici profesionale şi pot fi folosite simultan la dezvoltarea aplicaţiilor pentru zeci de utilizatori. Pentru aplicaţiile complexe din bănci, corporaţii, organizaţii şi instituţii de mari dimensiuni s-au impus SGBDR-urile de „categoria grea" : Oracle, DB2 (IBM), Informix (IBM), Sybase (Sybase), SQL Server (Microsoft). Acestea sunt mult mai robuste, mult mai fiabile, dar şi costisitoare. În ultimul timp şi-au făcut apariţia, ca alternative la sus-amintiţii coloşi, aşa-zisele SGBD-uri (aproape) gratuite, precum PostgreSQL, MySQL, mSQL, Firebird etc. Acestea rulează, de obicei, pe sisteme de operare de tip Linux (foarte ieftine) şi se întrevăd ca adversari serioşi ai marilor producători.

3.1 Relaţii/tabele, domenii, atribute, valori nule.
O bază de date relaţională (BDR) poate fi definită ca un ansamblu de relaţii (tabele); fiecare tabelă, alcătuită din linii (tupluri), are un nume unic şi este stocată pe suport extern (de obicei disc). La intersecţia unei linii cu o coloană se găseşte o valoare atomică. O relaţie conţine informaţii omogene legate de anumite entităţi, procese, fenomene: CĂRŢI, ELEVI, LOCALITĂŢI, PERSONAL, FACTURI etc. Spre exemplu, în fig. 4.1este reprezentată tabela STUDENTI ce stochează informaţii privitoare la studenții înscriși la cursurile unei facultăți. relație/tabela atribute/coloane 14

tuplu Fig. 3.1 Relația STUDENTI

domenii

În teoria relaţională se foloseşte termenul relaţie. Practica însă a consacrat termenul tabelă (engl. table). Un tuplu sau o linie este o succesiune de valori de diferite tipuri. în general, o linie grupează informaţii referitoare la un obiect, eveniment etc., altfel spus, informaţii referitoare la o entitate: o carte, un/o student(ă), o localitate, un angajat al firmei, o factură emisă etc. în figură 3.1 este pus în evidenţă al saselea tuplu din tabela STUDENTI, tuplu referitor la studentul Ionescu Gh Vasile. Linia respectivă este alcătuită din opt valori ce desemnează: Numărul matricol al studentului; numele, inițiala tatălui si prenumele; codul numeric personal; adresa; anul de studiu; serie; grupa; tipul de bursa de care beneficiază. Teoretic, orice tuplu reprezintă o relaţie între clase de valori (în cazul nostru, între opt clase de valori); de aici provine sintagma baze de date relaţionale, în sensul matematic al relaţiei, de asociere a două sau mai multe elemente. Fireşte, toate tuplurile relaţiei au acelaşi format. Ordinea tuplurilor nu prezintă importanţă din punctul de vedere al conţinutului informaţional al tabelei. Fiecare atribut este caracterizat printr-un nume şi un domeniu de valori pe care le poate lua. Domeniul poate fi definit ca ansamblul valorilor acceptate pentru un element component al relaţiei5:
-

într-o tabelă destinată datelor generale ale angajaţilor, pentru atributul Sex, domeniul este alcătuit din două valori: femeiesc şi bărbătesc; domeniul atributului judeţ este alcătuit din numele fiecărui judeţ (plus Bucureşti);

-

5

Marin Fotache – Proiectarea bazelor de date . Normalizarea si postnormalizare. Implementari SQL si Oracle Ed. Polirom 2005

15

-

domeniul unui atribut precum Preț_unitar, care se referă la preţul la care a fost vândut un produs/serviciu, este cu mult mai larg, fiind alcătuit din orice valoare cuprinsă între 1 şi 99999999999 lei (având în vedere rata inflaţiei).

Reţinem corespondenţa noţiunilor relaţie-tabelă, tuplu-linie şi atribul-coloană. Numărul de tabele pe cate le conţine o bază de date, atributele „adunate" în fiecare tabelă, domeniul fiecăruia dintre atribute prezintă diferenţe majore de la o bază la alta, chiar dacă uneori reflectă acelaşi tip de procese. Intrăm astfel în sfera proiectării bazelor de date, a dependenţelor şi normalizării. Principalele caracteristici ale unei relaţii sunt: -

în cadrul unei baze de date, o relaţie prezintă un nume distinct de al celorlalte relaţii; valoarea unui atribut într-un tuplu oarecare conţine a singură valoare (o valoare atomică) fiecare atribut are un nume distinct; orice valoare a unui atribut face parte din domeniul pe care a fost definit acesta; ordinea dispunerii atributelor în relaţie nu prezintă importanţă; flecare tuplu este distinct, adică nu pot exista două tupluri identice; ordinea tuplurilor nu influenţează conţinutul informaţional al relaţiei.

-

3.2. Restricţii ale bazei de date.
Principalele restricţii definibile în modelul relaţional sunt: de domeniu, de nenulitate, de atomicitate, de unicitate, referenţială şi cele definite de utilizator. Restricţia de domeniu. După cum am văzut în paragraful anterior, un atribut este definit printr-un nume şi un domeniu. Orice valoare a atributului trebuie să se încadreze în domeniul definit. Există mai multe moduri de percepţie a acestei restricţii. O parte din informaticieni substituie domeniul tipului atributului: numeric, şir de caractere, dată calendaristică, logic (boolean) etc, şi, eventual, lungimii (numărul maxim de poziţii/ caractere pe care se poate „întinde" un atribut). După cum 16

se observă, este luat în calcul numai aspectul sintactic al domeniului. Faptul ca anul de studiu al unei clase poate fii una dintre valorile 9, 10, 11, 12 reprezintă o restricție de comportament sau mai simplu o restricție definita de utilizator. Cea de-a doua categorie priveşte deopotrivă domeniile sintactic şi semantic. Astfel, domeniul sintactic al atributului LitClasa (litera) dintr-o relaţie precum ELEVI_LICEU este un caracter, obligatoriu literă, şi chiar mai restrictiv, litera e obligatoriu majusculă. Din punct de vedere semantic, LitClasa poate lua una dintre valorile: A, B, C,..., în funcţie de numărul de clase dintr-un an de studiu (cinci clase de a IX-a, patru de a X-a etc.). Nenulitatea. Deşi inventată de însuşi E.F. Codd, valoarea nulă este vehement contestată de cea mai mare parte a liniei purist-relaţionale (Date, Darwen6, Pascal). Nu discutăm legitimitatea unei asemenea meta-valori, ci doar amintim că, într-o bază de date, unora dintre atribute li se poate interzice valoarea NULL. Atomicitate. Conform teoriei bazelor de date relaţionale, orice atribut al unei tabele oarecare trebuie să fie atomic, în sensul imposibilităţii descompunerii sale în alte atribute. Ĩn aceste condiţii, se spune că baza de date se află în prima formă normală sau prima formă normalizată (1NF). în tabela STUDENŢI un atribut cu valori neatomice poate fi considerat, pentru majoritatea situaţiilor, Adresa, întrucât valorile sale îngrămădesc elemente ce pot fi şi individualizate: strada, număr, bloc, scara, etaj, apartament, localitate şi judeţ. Unicitate. Într-o relaţie nu pot exista două linii identice (două linii care prezintă aceleaşi valori pentru toate atributele). Mai mult, majoritatea relaţiilor prezintă un atribut sau o combinaţie de atribute care diferenţiază cu siguranţă un tuplu de toate celelalte tupluri ale relaţiei. Cheia primară a unei relaţii (tabele) este un atribut sau un grup de atribute care identifică fără ambiguitate fiecare tuplu (linie) al relaţiei (tabelei). Există trei restricţii pe care trebuie să le verifice cheia primară : 6

unicitate: o cheie identifică un singur tuplu (linie) al relaţiei;

Date, C.J., Darwen, H.,Foundation for Database Systems. The Third Manifesto, editia a II-a, Addison-Wesley, Reading,

Massachusetts, 2000

17

-

compoziţie minimala: atunci când cheia primară este compusă, nici un atribut din cheie nu poate fi eliminat fără distrugerea unicităţii tuplului în cadrul relaţiei; în cazuri limită, o cheie poate fi alcătuită din toate atributele relaţiei;

-

valori nenule : valorile atributului (sau ale ansamblului de atribute) ce desemnează cheia primară sunt întotdeauna specificate, deci nenule; mai mult, nici un atribut din compoziţia cheii primare nu poate avea valori nule. Cea dea treia condiţie se mai numeşte şi restricţie a entităţii.

Domeniul unui atribut care este cheie primară într-o relaţie este denumit domeniu primar. Dacă într-o relaţie există mai multe combinaţii de atribute care conferă unicitate tuplului, acestea sunt denumite chei candidate. O cheie candidată care nu este identificator primar este referită ca cheie alternativă. În tabela STUDENŢI există două chei candidate, Matricol şi CNP. Am ales Matricol drept cheie primară, CNP-ul devenind cheie alternativă. Dacă cheia primară a tabelei STUDENŢI este una simplă, există însă suficiente cazuri în care cheia primară este compusă din două, trei sau, la extrem, toate atributele relaţiei. Să luăm spre analiză o relaţie PERSONAL care conţine date generale despre angajaţii firmei. Fiecare tuplu al relaţiei se referă la un angajat, atributele fiind : Nume, Prenume, DataNașterii, Vechime, SalariuTarifar. • Atributul Nume nu poate fi cheie, deoarece chiar şi într-o întreprindere de talie mijlocie este posibil să existe doi angajaţi cu acelaşi nume. • Dacă apariţia a două persoane cu nume identice este posibilă, atunci apariţia a două persoane cu acelaşi Prenume este probabilă. • Nici unul dintre atributele Data Nașterii, Vechime şi Salariu Tarifar nu poate fi „înzestrat" cu funcţia de identificator. • In acest caz, se încearcă gruparea a două, trei, patru atribute, până când se obţine combinaţia care va permite diferenţierea clară a oricărei linii de toate celelalte. • Combinaţia Nume+Adresă pare, la prima vedere, a îndeplini „cerinţele" de identificator. Ar fi totuşi o problemă: dacă în aceeaşi firmă (organizaţie) lucrează împreună soţul şi soţia? Ambii au, de obicei, acelaşi nume de familie şi, tot de obicei, acelaşi domiciliu. Este adevărat, cazul ales nu este prea fericit. Dar este suficient pentru compromiterea combinaţiei. • Următoarea tentativă este grupul Nume + Prenume + Adresă, combinaţie neoperantă dacă în organizaţie lucrează tatăl şi un fiu (sau mama şi o fiică), având aceleaşi nume şi prenume şi domiciliul comun. 18

• Ar rămâne de ales una dintre soluţiile (Nume + Prenume +Adresă+Vechime) sau (Nume + Prenume + Adresa + DataNasterii). Oricare dintre cele două combinaţii prezintă riscul violării restricţiei de entitate, deoarece este posibil ca, la preluarea unui angajat în bază, să nu i se cunoască adresa sau data naşterii, caz în care atributul respectiv ar avea valoarea NULL. Dificultăţile de identificare fără ambiguitate a angajaţilor au determinat firmele ca, la angajare, să aloce fiecărei persoane un număr unic, număr denumit Marca. Prin adăugarea acestui atribut la cele existente, pentru relaţia PERSONAL, problema cheii primare este rezolvată mult mai simplu. Actualmente, sarcina este simplificată şi prin utilizarea codului numeric personal (CNP), combinaţie de 13 cifre care prezintă avantajul că rămâne neschimbată pe tot parcursul vieţii persoanei.

Restricţia referenţială O bază de date relaţională este alcătuită din relaţii (tabele) aflate în legătură. Stabilirea legăturii se bazează pe mecanismul cheii străine şi, implicit, al restricţiei referenţiale. De exemplu, avem o relaţie în care sunt implicate tabelele TIP_BURSE (Tip_bursa, Den_bursa, Cuantum_bursa) şi STUDENŢI ( Matricol, Nume_pren, CNP, Adresa, An_studiu, Seriem Grupa, Tip_bursa ). Atributul Tip_Bursa joacă un rol de „agent de legătură" între cele două relaţii. Pentru tabela TIP_BURSE, atributul Tip_bursa este cheie primară, în timp ce în tabela STUDENŢI, Tip_bursa reprezintă o coloană de referinţă sau cheie străină (externă), deoarece numai pe baza valorilor sale se poate face legătura cu relaţia-părinte TIP_BURSE. Cheile străine sau coloanele de referinţă sunt deci atribute sau combinaţii de atribute care pun în legătură linii (tupluri) din relaţii diferite. Tabela în care atributul de legătură este primar se numeşte tabelăpărinte (în cazul nostru, TIP_BURSE), iar cealaltă, tabelă-copil. Legat de noţiunea de cheie străină apare conceptul de restricţie referenţială. O restricţie de integritate referenţială apare atunci când o relaţie face referinţă la o altă relaţie. Când două tabele (relaţii), T1 şi T2, prezintă atributul sau grupul de atribute notat
CH,

care pentru T1 este
CH

cheie primară, iar pentru T2, cheie străină, daca în T2 se interzice apariţia de valori nenule ale referenţială.

care nu există în nici un tuplu din TI, se spune ca între T2 şi TI s-a instituit o restricţie Instituirea restricţiei referenţiale între tabelele TIP_BURSE (părinte) şi STUDENŢI (copil) permite cunoaşterea, pentru fiecare student, a denumirii bursei şi a cuantumului lunar. 19

Restricții-utilizator. Restricţiile-utilizator mai sunt denumite şi restricţii de comportament sau restricţii ale organizaţiei. De obicei, aceste restricţii iau forma unor reguli de validare la nivel de atribut, la nivel de linie sau de tabelă sau a unor reguli implementate prin declanşatoare(triggers). Spre exemplu, se poate institui o regulă care interzice emiterea unei noi facturi (o nouă vânzare) dacă datoriile firmei client sunt mai mari de 2.000.000.000 lei, iar directorul acesteia nu este membru în partidul/partidele de guvernământ.

3.3. Normalizarea
Proiectarea bazelor de date relaţionale (BDR) presupune definirea atributelor, gruparea lor în tabele, stabilirea legăturilor dintre ele, a mecanismelor de integritate şi securitate, fiind un proces dificil în care cunoştinţele teoretice, experienţa, inteligenţa, intuiţia şi creativitatea proiectanţilor se îmbină într-un mod mai mult sau mai puţin armonios. Structura finală a BD trebuie să asigure un echilibru între, obţinerea unui volum maxim de informaţii într-un interval de timp cât mai scurt şi, eliminarea anomaliilor de stocare şi actualizare, toate în condiţiile unui grad apreciabil de securitate şi integritate. Elaborarea schemei unei BD poate începe cu gruparea tuturor atributelor bazei de date într-o singură tabelă (relaţie universală). Dincolo de avantajul compactităţii, lucrul cu o singură relaţie atotcuprinzătoare ridică serioase probleme privind redundanţa datelor şi generează anomalii importante la adăugarea, modificarea sau ştergerea unor linii (tupluri). Ca o consecinţă directă, este necesară spargerea bazei în mai multe tabele care să fie legate prin restricţii de integritate referenţială. Este tocmai obiectivul central al normalizării. Spargerea relaţiei nu trebuie făcută oricum, deoarece apare riscul pierderilor de informaţii. De asemenea, un număr prea mare de tabele necesită un efort sporit pentru controlul bazei şi respectarea restricţiilor. In plus, trebuie să ţinem seama de faptul că obţinerea multor informaţii dintr-o bază de date fragmentată este posibilă prin operaţiunea de joncţiune, mare consumatoare de resurse. 20

Principalele obiective ale normalizării sunt : -

minimizarea spațialului necesar stocării datelor; minimizarea riscului apariţiei de date inconsistente în cadrul BD; minimizarea anomaliilor ce pot apărea la actualizare (inserarea datelor, dar mai ales modificări şi ştergeri); ameliorarea structurii bazei, reprezentarea diverselor conexiuni dintre atributele bazei; diminuarea nevoii de reorganizare periodică a modelului.

-

Codd, părintele modelului relaţional, a definit iniţial trei forme normale, notate prin 1NF, 2NF şi 3NF. Întrucât, într-o primă formulare, definiţia 3NF ridica ceva probleme, Codd şi Boyce au elaborat o nouă variantă, cunoscută sub numele Boyce-Codd Normal Form (BCNF). Deşi este vorba, în principiu, despre o formulare mai riguroasă a aceleiaşi 3FN, BCNF este prezentată separat în majoritatea lucrărilor. Formele 4 şi 5, legate de numele lui Ronald Fagin, sunt tratate mai cu reţinere, în literatura consacrată analizei şi proiectării bazelor de date. Ba chiar unele lucrări cu tentă mai pragmatică se opresc declarat la 3FN, pe care o consideră suficientă în elaborarea BDR. Etapele normalizării Fundamentul normalizării BDR îl constituie dependenţele dintre atribute. Primele trei forme normale pot fi determinate pe baza dependenţelor funcţionale elementare (totale) şi tranzitive. Forma a patra (4FN) se bazează pe dependenţele multivaloare, în timp ce a cincea formă normală (5FN) - pe dependenţele de joncţiune. Problema este că dependenţele multivaloare şi mai ales cele de joncţiune sunt dificil de identificat şi rar întâlnite în practică. Normalizarea BDR poate fi imaginată ca un proces prin care, pornindu-se de la relaţia iniţială R (universală), se realizează descompunerea succesivă a acesteia în subrelaţii, după succesiunea din Fig 4.27. Relaţia R poate fi ulterior reconstruită din cele n relaţii obţinute în urma normalizării, prin operaţii de joncţiune aplicate asupra acestora. Normalizarea reflectă relaţii care se manifestă între atribute ale bazei. Este imposibil de normalizat o relaţie fără a cunoaşte fenomenul, procesul pe care îl reflectă.

7

Oprea, D., Analiza sistemelor informationale, Editura Polirom, Iasi, 1999

21

Descompunere fără pierdere de informaţii Prin normalizare se încearcă a se elimina redundanţe şi anomalii manifestate la actualizare. Eliminarea se realizează prin „sfărâmarea" relaţiei în două sau mai multe relaţii „legate" prin restricţii de integritate referenţială. Ulterior, prin operaţiuni de joncţiune, tabela Început iniţială poate fi recompusă, ori de câte ori va fi cazul.universala - R Relație Cu cât „desfacem" relaţia iniţială (universală) în mai multe tabele, cu atât redundanţa
Exista evocate. Există însă o limită, deoarece la datelor este mai redusă si implicit, anomaliile grupuri repetitive ? Atomizarea atributelor descompunere trebuie avută în vedere păstrarea unor structuri care să permită, ulterior, obţinerea

informaţiilor necesare prin operaţiuni de joncţiune (apare noţiunea de joncţiune conservativă).
Relația R are cheie primara? Descompunere in relații ce au cheie primara

NU
1FN Exista DF parțiale ?

DA

NU
2FN

DA

Aducerea relațiilor in 2FN

Exista DF tranzitive ?

NU

DA

Aducerea relațiilor in 3FN

3FN

NU
Aducerea relațiilor in BCFN

Toți determinanții sunt chei candidate ?

DA

BCNF

NU

Exista DF multivaloare?

DA
Aducerea relațiilor in 4FN

4FN Exista dependențe de joncțiune?

NU

DA
Aducerea relațiilor in 5FN

22

5FN Sfârșit

NU

DA

Fig. 3.2 Etapele clasice ale normalizării bazelor de date relaționale Relaţia universală Prima etapă a normalizării constă în identificarea informaţiilor ce trebuie stocate şi gestionate cu ajutorul bazei de date. Noţiunea de relaţie universală este unul dintre destulele ingrediente ale modelului relaţional. Noi o să considerăm relaţia universală drept relaţia alcătuită din toate atributele identificate ca fiind relevante pentru aplicaţie şi toate tuplurile posibile cu valorile acestor atribute. Prin urmare, schema relaţiei universale trebuie sa conțină toate atributele bazei de date.

3.4. Prima formă normalizată – 1NF
Prima formă normalizată (1NF) este, în general, tratată cu superficialitate de majoritatea practicienilor în materie de proiectare a bazelor de date. Aceasta deoarece principala cerinţă atomicitatea valorilor - este un deziderat uşor de îndeplinit, cel puţin la prima vedere. Cele mai sensibile chestiuni în aducerea relaţiilor în INF sunt legate de atomicitate, eliminarea grupurilor repetitive, precum şi de stabilirea cheii primare, care devine o problemă delicată atunci când se porneşte de la o relaţie cu zeci sau sute de atribute. Definiţii ale primei forme normalizate După Codd, o relaţie este în prima formă normală dacă [...] nici unul dintre domeniile sale nu conţine elemente care sunt, la rândul lor, seturi (ansambluri)8.Se cuvine de adăugat

8

Codd,E.F.”Further Normalization of the Database Relational Model”, Database Systems, Courant Computer Science Symposia

Series, vol.6, Englewood Cliffs, N.J., Prentice Hall, 1972.

23

remarca lui Date care crede că ar fi fost mai nimerit ca, în locul termenului domenii, Codd să-1 fi folosit pe cel de atribute. Unele lucrări definesc o relaţie aflată în 1NF ca acea relaţie în care fiecare atribut prezintă numai valori atomice, adică toate atributele sunt nedecompozabile; după R. Riordan, o relaţie este în INF dacă domeniile pe care sunt definite atributele relaţiei sunt scalare9. În ediţia a treia a cărţii dedicate sistemelor de baze de date, Connoly şi Begg sunt mai tranşanţi: o relaţie în 1NF este o relaţie în care intersecţia oricărei linii cu oricare coloană conţine o valoare si numai una.10 Astfel, 1NF respinge ideea de set de valori, tuplu de valori sau combinaţia acestora ca valoare a unui singur atribut pe un oricare tuplu (linie) a relaţiei. Formularea care a generat cele mai multe confuzii este legată de noţiunea de grupuri repetitive: o relaţie în 1NF nu trebuie să conţină grupuri repetitive. De obicei, noţiunea de grup repetitiv este raportată direct la cea de atomicitate. O relaţie este în 1 NF dacă domeniile pe care sunt definite atributele relaţiei sunt constituite numai din valori atomice (elementare), în plus, un tuplu nu trebuie să conţină atribute sau grupuri de atribute repetitive
Definiţia lui Toby Teorey, spune ca o relaţie este în 1NF dacă şi numai dacă toate

coloanele conţin numai valori atomice; aceasta înseamnă că nu există grupuri (coloane) repetitive în cadrul vreunei linii a tabelei. Imediat autoarea precizează că un grup repetitiv apare într-o tabelă atunci când unui atribut multi-valoare îi sunt permise două sau mai multe valori reprezentate în cadrul unei aceleiaşi linii.11 Aducerea unei relaţii în INF presupune discutarea următoarelor elemente: raportul atribut simplu/atribut compus; grupuri repetitive de atribute (pe orizontală); grupuri repetitive de valori în cadrul fiecărei celule a tabelei.

Atribute simple şi atribute compuse Primele vizate de „stigmatul" neatomicităţii sunt atributele compuse.Un exemplu celebru privind atribute compuse (non-atomice) este Adresa. Fiind alcătuită din Stradă, Număr, Bloc,
9

Riordan, R., Designing Relational Database Systems, Microsoft Press, 1999 Connolly, T., Begg, C.E., Database Systems. A practical Approach to Design, Implementation and Management, editia a III-a

10

Addison-Wesley, Harlow, 2002
11

Teorey, T.J., Database Modeling & Design, Morgan Kaufman, San Francisco, 1999

24

Scară, Etaj, Apartament, plus CodPoştal (după noul sistem de codificare), discuţia despre atomicitatea adresei pare de prisos, iar descompunerea sa imperativă. Din nou însă trebuie să ne raportăm la obiectivele bazei. Fără îndoială că, pentru BD a unei filiale CONEL sau ROMTELECOM, sau pentru Poliţie, preluarea separată a fiecărui element constituent al adresei este vitală. Interesează, spre exemplu, ce abonaţi sunt pe strada Tranziţiei sau câte cereri sunt depuse de cetăţenii de pe străzile Lascăr Catargi, Titu Maiorescu si Marina Scupra. Alte exemple de atribute ce pot fi considerate, în funcţie de circumstanţe, simple sau compuse: trei litere). Despre grupuri repetitive şi urmările lor O relaţie (tabelă) în 1NF nu trebuie să conţină atribute care se repetă ca grupuri. Intr-o altă formulare, toate liniile unei tabele trebuie să conţină acelaşi număr de atribute. Fiecare celulă a tabelei, altfel spus, valoarea unui atribut pe o linie, trebuie sa fie atomică. Un grup repetitiv este un atribut sau grup de atribute dintr-o tabelă care apare cu valori multiple pentru o singură apariţie a cheii primare a tabelei nenormalizate. Să luăm exemplul tabelei BIBLIOTECĂ_1 din Fig.3.3. Tabela gestionează informaţii despre cărţile existente în depozitul bibliotecii UTM Pitesti. De remarcat că în bibliotecă există două exemplare ale cărţii cu ISBN-ul 973-683-709-2 şi trei exemplare de cea dedicată Visual FoxPro. Prima carte a fost scrisă de patru autori şi ei îi sunt asociate opt cuvinte-cheie, iar a doua are un singur autor. Relaţia nenormalizată conţine trei grupuri repetitive: Cote, Autori şi CuvinteCheie.
BIBLIOTECA ISBN
973-683-889-7 973-683-709-2

DataOperaţiuniiBancare

(Data+Ora),

BuletiIldentitate

(Seria+Număr),

NrînmatriculareAuto (privit global, sau pe cele trei componente : judeţ, număr şi combinaţia de

Titlu
Visual Fox Pro. Ghidul dezvoltarii aplicatiilor profesionale SQL. Dialecte DB2, Oraclesi Visual FoxPro

Cota
III-13421, III-13422, III-13423 III- 10678, III-10679

Autori
Marin Fotache, Ioan Brava, Catalin Strambei,Liviu Cretu Marin Fotache

Editura
Polirom Polirom

LocSediuEd
Iasi Iasi

AnAparitie
2002 2001

CuvinteCheie
baze de date,SQL, proceduri stocate, Fox Pro, formulare, orientare pe obiect , client-server, Web baze de date, algebra relationala, SQL

Fig. 3.3. Relatia Biblioteca_1 25

Una dintre cele mai nerecomandate soluţii pentru eliminarea grupurilor repetitive ţine de extinderea pe orizontală a tabelelor, prin duplicarea forţată a unor atribute. Pentru a înlătura grupurile repetitive de pe primele două linii, putem fi tentaţi să modificăm structura tabelei, ca in urmatoarea structura : Biblioteca_2 ( ISBN, Titlu, Cota1, Cota2, Cota3, Autor1, Autor2, Autor3, Autor4, Editura, LocSediuEd, AnAparitie, CuvantCheie1, CuvantCheie2, CuvantCheie3, CuvantCheie4, CuvantCheie5, CuvantCheie6, CuvantCheie7) Deşi tabela se află în prima formă normală, structura acesteia este hilară. Ar trebui să „rezervăm" câteva zeci de atribute pentru cotele cărţilor, altă serie de atribute pentru autori, ca să nu mai vorbim de cuvintele-cheie. Deşi hilară, schema de mai sus nu violează conceptul de atomicitate, oricare ar fi formularea acestuia. Eliminarea grupurilor repetitive prin adăugarea de tupluri A doua variantă păstrează structura relaţiei, în sensul că nu se modifică numărul de atribute, adăugându-se tupluri (linii) suplimentare astfel încât orice valoare a celor trei atribute de tipul „grupuri repetitive" să devină atomică. Apare însă problema: cum anume completăm tuplurile pentru ca să fie preluate toate informaţiile, iar, pe de altă parte, eventualele actualizări să nu antreneze pierderi sau alterări de informaţii. În acest sens, am putea lua în discuţie trei soluţii, după cum urmează: Număr minim de linii - o singură valoare atomică pentru flecare atribut compozit. Avem trei atribute non-atomice (multivaloare), pentru fiecare carte, numărul de linii din tabelă va fi maximul dintre numărul cotelor, numărul autorilor şi numărul cuvintelor-cheie. Astfel, pentru Visual FoxPro sunt trei cote, patru autori şi opt cuvinte-cheie; aşadar, vom avea opt linii. Valorile cotelor în liniile 4-8 vor fi NULL; la fel şi valorile atribului Autor pentru liniile 5-8. Deoarece o cotă nu poate identifica decât o singură carte, cheia primară a noii relaţii este alcătuită din trei atribute (Cotă. Autor, Cuvântcheie). Redundanţa datelor este evidentă. Dacă pentru cartea de Visual FoxPro am dori să mai introducem un nou cuvânt-cheie, ar trebui inserată o linie nouă în tabelă, în care valorile atributelor Autor şi Cotă să fie NULL. Aceasta nu este însă singura problemă. Să presupunem că sintagma proceduri stocate este greşit asociată cărţii de Visual FoxPro. în mod normal, corectarea acestei greşeli presupune ştergerea celui de-al treilea tuplu: 26

DELETE FROM BIBLIOTECĂ_2 WHERE ISBN - '97 3-683-8 8 9-7' AND cuvântcheie = 'proceduri stocate') Necazul e că ştergerea liniei se face cu două pierderi de informaţii. Prima pierdere ţine de calitatea de coautor ai acestei cărţi a lui Cătălin Strîmbei, iar a doua este legată de exemplarul cărţii ce are cota III-13423. Aceasta deoarece tuplul şters era singurul care se referea la autorul şi la cota cu pricina. Am putea încerca un artificiu, şi anume ca ştergerea unui cuvânt-cheie, a unui autor ori a unei cote să nu se facă prin ştergerea liniei respective, ci prin setarea pe NULL a valorii de pe linia incriminată: UPDATE BIBLIOTECĂ _2 SET cuvântcheie = NULL WHERE ISBN = '97 3-68 3-8 8 9-7' AND cuvântcheie = ('proceduri stocate') Nici această idee nu e din cale-afară de inteligentă. Dacă am dori eliminarea sintagmei Web pentru aceeaşi carte: UPDATE BIBLIOTECĂ_2 SET cuvântcheie = NULL WHERE ISBN - '97 3-683-68 9-7' AND cuvântcheie = 'Web') atunci linia modificată devine cu totul de prisos în tabelă, toate cele trei atribute, cota, Autor şi cuvântcheie, având valori NULL. Cu alte cuvinte, după modificare, tuplul nu spune nimic, nu are valoare informaţională. Practic, după fiecare NULL-izare pe o linie a unuia dintre cele trei atribute, trebuie verificat dacă pe linia respectivă celelalte două atribute au valori NULL, caz în care linia se poate şterge. Mai există o problemă şi din punct de vedere al conţinutului informaţional. Să presupunem că ne interesează să aflăm care sunt autorii ce au scris despre SQL. Ţinând seama de stuctura relaţiei de mai sus, am fi tentaţi să folosim o selecţie după cuvântul-cheie SQL, urmată de o proiecţie a valorilor atributului Autor : SELECT autor FROM BIBLIOTECĂ_2 WHERE cuvântcheie = ( 'SQL')

27

Rezultatul furnizat este alcătuit din două linii, una ce conţine valoarea Ioan Brava, iar cealaltă valoarea NULL. Lipsesc deci ceilalţi trei autori ai cărţii despre Visual FoxPro, dintre care unul a scris chiar o carte despre SQL. Interogarea ce furnizează răspunsul corect trebuie să folosească o joncţiune sau corelare după atributul ISBN. Prin urmare, este necesar de ştiut că structura informaţională pe care o reprezintă tabela de mai sus are o serie de neajunsuri. Cel mai bine întemeiat motiv de renunţare la această variantă este prezenţa valorilor nule în componenţa atributelor chei primare. Număr de linii egal cu suma valorilor elementare ale atributelor de tip grup repetitiv. A doua soluţie de completare are în vedere eliminarea problemei care apare la ştergerea unei linii în cazul soluţiei precedente, şi anume: pe oricare linie, o valoare nenulă a unuia dintre cele trei atribute atrage după sine nulitatea celorlalte două. Spre exemplu, prima carte are 3 cote, 4 autori şi 8 cuvinte-cheie; prin urmare, vor fi necesare 3 + 4 + 8 = 15 linii. Această secundă soluţie, deşi presupune un număr mai mare de linii, elimină necazul pierderii involuntare de informaţii. Astfel, ştergerea unui cuvânt-cheie nu va afecta, cu siguranţă, nici un autor sau exemplar al cărţii respective. Ca şi în cazul soluţiei anterioare, indezirabilitatea variantei este legată de prezenţa valorilor nule în componenţa atributelor chei primare. Număr maxim de linii, egal cu produsul valorilor elementare ale atributelor de tip grup repetitiv. De data aceasta, tăiem valorile nule de la rădăcină, introducând în relaţie toate combinaţiile Autor-Cota-CuvântCheie. Cum prima carte are 3 cote, 4 autori şi 8 cuvinte-cheie, în relaţia BIBLIOTECĂ_3 vor exista 3 * 4 * 8 = 96 de tupluri referitoare la aceasta. Aducerea relaţiei în 1NF eliminând grupurile repetitive prin adăugarea de noi tupluri de această manieră se dovedeşte mai mult decât costisitoare. Aceasta nu numai din punctul de vedere al spaţiului excesiv consumat din pricina redundanţei masive, dar şi dacă ne gândim la anomaliile de actualizare. Spre exemplu, pentru a nu pierde informaţii, atunci când adăugăm un cuvânt-cheie nou pentru cartea luată spre analiză, e nevoie să inserăm în tabelă nu mai puţin de 3 (cote) * 4 (autori) = 12 Unii. Dezvoltând această idee optimistă, imaginaţi-vă cum stau lucrurile

28

pentru o lucrare monumentală cu 10 autori şi 78 de cuvinte-cheie din care în bibliotecă există 40 de exemplare !?!?!

Eliminarea grupurilor repetitive prin construirea de noi relaţii. Consta în „ruperea" din relaţia universală a grupurilor şi constituirea de relaţii noi. Spre exemplu, pentru aducerea unei relaţii în 1NF parcurgem patru paşi: în relaţia universală, în locul atributelor compuse se trec componentele acestora, ca atribute simple; se constituie cate o relație pentru fiecare grup repetitiv; in schema fiecărei noi relații obținute la pasul doi se introduce si cheia primara a relației nenormalizate; cheia primara a fiecărei noi relații va fii compusa din atributele/atributele chei ale relației plus unul sau mai multe atribute proprii. Aplicand acest algoritm la relatia Biblioteca_1 , obtinem patru tabele : Cote ( ISBN, Cota), Autori_Carti (ISBN, Autor) , Carti_Cuvcheie (ISBN, Cuvantcheie) , Carti(ISBN, Titlu, Editura, LocSediuEd, AnAparitie). Structura obţinută se detaşează prin cel mai mic volum de redundanţă de până acum, ceea ce antrenează şi economii de stocare, şi reducerea sensibilă a anomaliilor de actualizare. Personal însă, reproşez acestui stil de normalizare bazat pe eliminarea grupurilor repetitive caracterul prea „ochiometric". Observarea grupurilor repetitive depinde decisiv de ordinea în care sunt dispuse atributele în relaţie (teoria relaţională prevede clar că nici ordinea coloanelor, nici cea a liniilor nu influenţează conţinutul informaţional al unei tabele). Să discutăm relaţia BIBLIOTECĂ_4, ce are aceeaşi structură ca BIBLIOTECĂ_1, dar ordinea atributelor este schimbată - vezi figura 3.4. Tabela BIBLIOTECĂ_4 este mai aproape de realitate decât BIBLIOTECĂ_1. În depozit sunt trei exemplare ale cărţii dedicate Visual FoxPro, acestora corespunzând cu trei tupluri în
BIBLIOTECA_4 Cota III-13421 III-13422

ISBN 973-683-889-7 973-683-889-7

Titlu Visual Fox Pro. Ghidul dezvoltarii aplicatiilor profesionale Visual Fox Pro. Ghidul dezvoltarii aplicatiilor profesionale

Autori Marin Fotache, Ioan Brava, Catalin Strambei,Liviu Cretu Marin Fotache, Ioan Brava, Catalin Strambei,Liviu Cretu

29

III-13423 III- 10678 III-10679 Editura Polirom Polirom Polirom Polirom Polirom

973-683-889-7 973-683-709-2 973-683-709-2 LocSediuEd Iasi Iasi Iasi Iasi Iasi

Visual Fox Pro. Ghidul dezvoltarii aplicatiilor profesionale SQL. Dialecte DB2, Oraclesi Visual FoxPro SQL. Dialecte DB2, Oraclesi Visual FoxPro AnAparitie 2002 2002 2002 2001 2001

Marin Fotache, Ioan Brava, Catalin Strambei,Liviu Cretu Marin Fotache Marin Fotache

CuvinteCheie baze de date,SQL, proceduri stocate, Fox Pro, formulare, orientare pe obiect , client-server, Web baze de date,SQL, proceduri stocate, Fox Pro, formulare, orientare pe obiect , client-server, Web baze de date,SQL, proceduri stocate, Fox Pro, formulare, orientare pe obiect , client-server, Web baze de date, algebra relationala, SQL baze de date, algebra relationala, SQL

Fig. 3.4. Relația Biblioteca_4 noua relaţie. Cheia primară este Cotă (observaţi că ISBN se repetă pe primele trei linii şi pe ultimele două). După calapodul aplicat ceva mai sus, există două grupuri repetitive, Autori şi Cuvintecheie. Drept care ne grăbim să descompunem relaţia universală in trei relaţii aflate in 1NF, dupa cum urmeaza:
-

Cote_Autori (Cota, Autori ), Cote_Cuvcheie (Cota, Cuvantcheie), Carti (Cota, ISBN, Titlu, Editura, LocSediuEd, AnAparitie).

Aceasta reprezentand prima forma normalizata a relatiei Biblioteca_4. Pentru remedierea problemelor cauzate de caracterul arbitrar al dispunerii atributelor în relaţie, am putea institui o regulă: se începe cu atributele cele mai generale („non-repetitive") şi se continuă apoi către cele mai „repetitive". în cazul relaţiei BIBLIOTECĂ, s-ar putea începe cu, ISBN-ul continuând cu Titlu, Editură, LocSediuEd, AnApariţie, apoi Autori şi CuvinteCheie. Prima formă normală şi problema cheii primare a relaţiei universale. De cele mai multe ori, constituirea unei relaţii universale atotcuprinzătoare se loveşte de o problemă majoră - cea a cheii primare. Modelul relaţional prezintă două restricţii esenţiale vizavi de cheia primară: unicitate şi valori nenule pentru atributele din alcătuirea cheii (restricţia de entitate). 30

Dacă dorim să identificăm fiecare linie a relaţiei, trebuie să definim, în cele mai multe situaţii, o cheie primară cu mai multe atribute, care însă în anumite tupluri ar avea valori nule. Pe de altă parte, dacă nu vrem să fie violată restricţia de entitate, trebuie să renunţăm la a prelua în relaţia universală linii vitale din punctul de vedere al conţinutului informaţional al bazei de date. Sa luam exemplu relația Biblioteca_4. Sa studiem toate atributele si sa vedem care ar putea sa fie cheie primara pentru aceasta relație. CuvinteCheie nu ar putea sa fie cheie primara deoarece nu îndeplinește conditia de unicitate a cheii, se tot repeta pentru carti care studiaza aceleasi probleme ( „VisualFoxPro. Ghidul dezvoltarii aplicatiilor profesionale” si „SQL. Dialecte DB2, Oracle si Vizual FoxPro” au cuvinte cheie care se repeta : baze de date, SQL). Deci nu ne defineste tuplul ca fiind unic. AnAparitie, in nici un caz nu poate sa indeplineasca conditiile , pentru ca intr-un an se scot foarte multe carţi pe piaţa. In aceiaşi situaţie se afla si LocSediuEd, Editura. Autorii , pot scoate pe piața mai multe cărţi, atributul Autori , nu îndeplinește condiţia de unicitate. Titlu, ar putea sa fie cheie candidata pentru o carte , dar sa nu uitam ca intr-o biblioteca nu se găsesc numai cate un exemplar dintr-un anumit titlu de carte si mai sunt si reeditările, care la rândul lor se pot suprapune peste prima ediție apăruta pe piață. ISBN, este intr-adevăr o cheie candidata la cheia primara, nu poate avea valori nule, este unic pentru un anumit titlu de carte, scos intr-o ediție dar se tipăresc mai multe exemplare din același titlu. Deci, nici atributul ISBN nu poate fii cheie primara in aceasta relație. Cota, un ansamblu de semne, simboluri , cifre, litere care indică locul unor cărţi, al unor documente într-o bibliotecă, într-un inventar12. Acest atribut îndeplinește condiția de unicitate a cheii si nu poate lua valori nenule. Ea definește un singur tuplu din tabelul nostru. Este cheie primara , unica.

3.5. A doua forma normalizata – 2NF
Cea de-a doua formă normală (2NF) se bazează pe dependenţele funcţionale totale sau elementare. Dependente funcţionale Problema stabilirii dependenţelor dintre atribute este fundamentală în procesul elaborării bazelor de date relaţionale. Aducerea structurii bazei într-o variantă care minimizează
12

http://www.webdex.ro/online/dictionar/cot%C4%83

31

redundanţele şi anomaliile manifestate la adăugarea/modificarea/ştergerea unor linii din tabele presupune parcurgerea unui proces de normalizare a relaţiilor, normalizare care este centrată tocmai pe conceptul de dependenţă între atributele bazei. Definiţie Dependenţa funcţională reprezintă o generalizare a conceptului de cheie primară. Desemnăm prin Data2 un atribut sau o combinaţie de atribute dintr-o relaţie oarecare şi prin Data1 un alt atribut sau grup de atribute din aceeaşi relaţie. Se spune că Data2 este în dependenţă funcţională (sau depinde funcţional) de Data1 atunci când cunoaşterea unei valori pentru Data1 permite determinarea (cunoaşterea) a maximum o valoare pentru Data2. Data1 se numeşte sursa sau determinantul dependenţei funcţionale, iar Data2 reprezintă destinaţia (scopul sau determinatul) dependenţei funcţionale. Formal, dacă notăm relaţia R {A1 A2,…, An} - unde R este numele relaţiei şi Ai sunt atributele relaţiei R - şi prin X şi Y două subansambluri din {A1 A2,...,An}, se spune că există o dependenţă funcţională între X şi Y (simbolizată X->Y) dacă şi numai dacă: • fiecare apariţie (valoare) a lui X poate fi asociată unei singure apariţii a lui Y ; • două apariţii identice ale lui X nu pot fi asociate decât aceleiaşi apariţii a lui Y. Dependenţele funcţionale reprezintă legături semantice între atribute ale bazei de date. Dependenţe funcţionale cu sursa compusă Există dependenţe funcţionale care prezintă în partea stângă (sursa dependenţei funcţionale sau determinantul) două sau mai multe atribute. Acestea sunt dependenţele funcţionale cu sursa compusă. Relaţia BIBLIOTECĂ_3 (ISBN, Titlu, Cota, Autor, Editura, LocSediuEd, AnAparitie, CuvantCheie), aflată în prima formă normală, prezintă ca cheie primară combinaţia (Cota, Autor, CuvântCheie). De aceea, se pot inventaria următoarele cinci dependenţe funcţionale, în care destinaţii sunt atributele necheie: (l)(Cota, Autor, CuvântCheie) -> ISBN (2)(Cota, Autor, CuvântCheie) -> Titlu (3)(Cota, Autor, CuvântCheie) -> Editura (4) (Cota, Autor, CuvântCheie) ->LocSediuEd (5)(Cota, Autor, CuvântCheie) -> AnApariţie 32

Alte elemente luate în discuţie pentru stabilirea DF: - o carte poate fi scrisă de mai mulţi autori: ISBN—/-> Autor ; - un autor scrie mai multe cărţi: Autor —/-> ISBN şi - despre mai multe subiecte: Autor —/-> CuvântCheie ; - într-o carte sunt tratate mai multe subiecte: ISBN —/-> CuvântCheie ; - pentru o carte sunt în depozit mai multe exemplare: ISBN —/-> Cota. Cota este codul care identifică în mod unic o carte aflată în depozit, aşadar: (6)Cota -> ISBN (7)Cota -> Titlu (8)Cota -> Editura (9) Cota -> LocSediuEd (10) Cota -> AnApariţie Fiecare titlu de carte este identificat fără ambiguitate de ISBN: (11) ISBN -> Titlu (12) ISBN -> Editura (13) ISBN -> LocSediuEd (14) ISBN -> AnApariţie O editură are un singur sediu central: (15)Editura -> LocSediuEd Prin urmare, dintre cele 15 DF inventariate, primele cinci au sursa compusă, celelalte, sursa simplă. Chiar pentru cazuri simple, ansamblul tuturor DF într-o bază de date poate să devină extrem de stufos. De aceea, în procesul normalizării trebuie avut în vedere un echilibru între: identificarea tuturor DF ce reflectă restricţii, reguli ale fenomenului/procesului modelat, includerea în setul DF numai a celor relevante, adică a unui ansamblu minimal din care, prin reguli de genul celor de mai sus, se pot obţine toate celelalte DF. In teorie, dat fiind un set de DF notat S, ansamblul tuturor DF determinate pe baza acestuia se numeşte închidere a lui S şi se notează S+.

33

Mult mai importantă este determinarea acoperirii minimale, adică a setului minim de DF prin care pot fi determinate toate celelalte dependenţe din relaţie. După Chris Date, un set S de dependeţe funcţionale este ireductibil dacă şi numai dacă satisface următoarele trei proprietăţi13: 1. Partea dreaptă (destinaţia) a fiecărei dependenţe din S implică un singur atribut. 2. Sursa fiecărei DF este ireductibilă, adică nici un atribut nu poate fi eliminat fără distrugerea dependenţei; se spune că DF este ireductibilă la stânga. 3. Nici o DF din S nu poate fi eliminată fără afectarea închiderii S +, altfel spus, fără pierderea unei serii de informaţii. Din păcate, deşi elegant postulată, acoperirea minimală ridică probleme majore chiar şi la un număr mediu de atribute, ca să nu vorbim cât de alunecoasă este proprietatea a treia formulată de Date. în plus, de multe ori, pentru o bază de date există mai multe acoperiri minimale. Lucrurile pot fi însă simplificate parţial eliminând din discuţie dependenţele simetrice şi redundante. Dependenţe funcţionale simetrice şi redundante Deseori, o bază de date sau relaţie prezintă mai multe chei candidate. Alegerea dintre acestea a cheii primare are în vedere, pe lângă unicitate, compoziţia minimală şi valorile nenule ale oricărui atribut component, precum şi elemente ce ţin de facilitatea utilizării: uşurinţa reţinerii (de către utilizator), lungime cât mai mică, constanţă în timp etc. În procesul normalizării, problemele ridicate de aceste dependenţe reciproce dintre cheile candidate trebuie tratate cu prudenţă. De cele mai multe ori, este recomandat ca dintre dependenţele unei relaţii să fie eliminate toate cele în care sursa este o cheie candidată şi păstrarea numai a celor în care determinantul este atributul cheie primară.

Reprezentări ale dependenţelor funcţionale Elaborarea structurii bazelor de date prin tehnica normalizării necesită o gestiune riguroasă a tuturor dependenţelor funcţionale. În practică, parcurgerea tuturor relaţiilor dintre atributele unei baze de date se poate solda cu identificarea a zeci sau chiar sute de dependenţe. Conectarea lor, determinarea redundanţelor, incluziunilor, tranzitivităţilor ridică astfel uneori

13

Date, C.J., Darwen, H.,Foundation for Database Systems. The Third Manifesto, editia a II-a, Addison-Wesley, Reading,

Massachusetts, 2000

34

probleme apăsătoare. Drept pentru care au fost elaborate diverse instrumente menite a simplifica vizualizarea şi lucrul cu DF: a) diagrame, b) grafuri şi c) matrice ale dependenţelor funcţionale. a) Diagrame ale DF Diagramele DF au o utilizare limitată, deoarece la un număr mare de atribute reprezentarea dependenţelor este foarte anevoioasă. O dependenţă dintre două atributeeste indicată printr-o linie (sau un număr de segmente) ce porneşte din sursă şi se termină printr-o săgeată „înfiptă" în destinaţie (determinant). Când sursele sau destinaţiile sunt compuse, atunci, mai întâi, se unesc atributele din grupul determinant/destinaţie, iar terminaţiile dependenţelor vizează segmentele de grup. Relaţia BIBLIOTECĂ_3 (ISBN, Titlu, Cota, Autor, Editura, LocSediuEd, AnAparitie, CuvantCheie). Diagrama dependenţelor acestei relaţii, este prezentată în figura de mai jos.

ISBN

Titlu

Cota

Autor

Editura

LocSediuEd AnAparitie CuvantCheie

Figura 3.5. Diagrama DF a relației BIBLIOTECĂ_3 b) Graful dependenţelor funcţionale Intr-un graf al dependenţelor funcţionale, acestea sunt reprezentate prin săgeţi ce leagă sursa şi destinaţia. La dependenţele funcţionale simple, săgeata uneşte cele două atribute. Când sursa este compusă, se foloseşte un conector care leagă, în primă instanţă, atributele determinant, iar săgeata uneşte acest conector cu atributul destinaţie. Cât priveşte dependenţele relației BIBLIOTECĂ_3 corespunzător diagramei din figura 3.5 este graful din figura următoare, în ciuda densităţii de săgeţi, se remarcă un plus de claritate şi folosirea mai judicioasă a spaţiului. Cota Autor CuvantCheie

35

ISBN

AnAparitie

Titlu

Editura

LocSediuEd

Fig. 3.6. Reprezentarea sub forma de graf a diagramei din fig.3.5. c) Matricea dependenţelor funcţionale Construirea matricei dependenţelor funcţionale demarează prin crearea unui tabel în care fiecărui atribut i se va asocia o linie şi o coloană. După includerea tuturor atributelor, se adaugă toate grupurile de atribute care constituie surse de dependenţe funcţionale. Apoi se parcurg, pe rând, coloanele, în fiecare celulă scriindu-se 1 atunci când atributul de pe coloană este sursă a unei DF în care destinaţia este atributul/ grupul de pe linie. Sursa de DF 1 2 6 9 1 2 3 4 5 6 7 8 9 Cota ISBN Autor CuvantCheie Titlu Editura LocSediuEd AnAparitie (Cota, Autor,CuvantCheie) 1 1

1 1 1 1

1 1 1 1

1

1 1 1 1

Fig. 4.7. Matricea corespunzătoare diagramei din fig 4.5. si a grafului din fig. 4.6.

Dependenţe funcţionale totale Noţiunea de dependenţă funcţională totală a fost introdusă de Melkanoff, O dependenţă funcţională Data1 -> Data2 este totală dacă nu există nici un atribut/combinaţie de atribute Dată3 ca subansamblu al Data1 care să verifice dependenţa funcţională Dată3 -> Dată2. 36

Formal, dacă x = {Ai, Aj, Ak} reprezintă un grup de atribute ale relaţiei R, iar Am un atribut al aceleiaşi relaţii, unde Am⊄X, se spune că există o dependenţă funcţională totală între X şi Am dacă: 1. X —>Am si 2. nu există nici un subansamblu S de atribute, S ⊂ X, pentru care S-> Am Se notează: Xtotal> Am Dependenţa funcţională totală mai este denumită şi elementară, plină, deplină sau completă. Implicit, toate dependenţele in care sursa este simplă (alcătuită dintr-un singur atribut) sunt dependenţe funcţionale complete. In relaţia BIBLIOTECĂ_3, primele cinci dependenţe funcţionale: (1) (Cota, Autor, CuvântCheie) -> ISBN (2) (Cota, Autor, CuvântCheie) -> Titlu (3) (Cota, Autor, CuvântCheie) -> Editura (4) (Cota, Autor, CuvântCheie) -> LocSediuEd (5) (Cota, Autor, CuvântCheie) ->AnApariţie sunt parţiale, deoarece: (6) Cota -> ISBN (7) Cota -> Titlu (8) Cota -> Editura (9) Cota -> LocSediuEd (10) Cota -> AnApariţie Cu alte cuvinte, un atribut component al determinatului dependenţelor (l)-(5) este, el singur, sursă într-o serie de DF în care destinaţiile sunt identice. Trecerea relaţiilor în a doua formă normală (2NF) Începând cu a doua formă normală, relaţiile pot fi decupate în subrelaţii, în scopul diminuării problemelor legate de stocare şi actualizare. În general, atunci când într-o relaţie R există o DF de tip x -> y şi x nu este cheie candidată, atunci R conţine o anumită doză de redundanţă. O relaţie se află în 2NF dacă: 1. Se află în 1NF. 2. Toate DF ce leagă cheia primară la celelalte atribute sunt DF elementare (totale). 37

O bază de date este în 2NF când toate relaţiile care o alcătuiesc sunt în 2NF. Problema trecerii unei relaţii din prima în a doua formă normală se pune numai când cheia primară a relaţiei este compusă din mai multe atribute. Într-o formulare mai lejeră, se poate spune că o relaţie în 2NF nu conţine DF parţiale între atributele cheie şi celelalte atribute. In general, trecerea de la 1NF la 2NF se poate realiza după următoarea succesiune de 6 paşi: 1. Se identifică posibila cheie primară a relației universale, care conferă unicitate oricărui tuplu din relaţie, chiar în condiţiile violării restricţiei de entitate. 2. Se inventariază toate dependenţele dintre atributele relaţiei (închiderea DF), cu excepţia celor în care destinaţia este un atribut component al cheii primare. 3. Se trec în revistă toate dependenţele care au ca sursă (determinant) un atribut sau subansamblu de atribute din cheia primară. 4. Pentru fiecare atribut (sau subansamblu) al cheii de la pasul 3 se creează o relaţie care va avea drept identificator primar atributul (subansamblul) respectiv, iar celelalte atribute vor fi cele care apar ca destinaţii în dependenţele de la pasul 3. 5. Din relaţia iniţială sunt eliminate toate atributele destinaţie (non-cheie) din relaţiile „proaspăt" obţinute, păstrându-se numai atributele cheie ale noilor relaţii (se asigură, astfel, cheile străine care vor face legăturile către noile relaţii). 6. In „rămăşiţele" relaţiei universale (iniţiale), se verifică dacă cheia primară iniţială respectă restricţia de entitate, iar dacă nu, se mai elimină dintre atribute, la limită, chiar toată relaţia-„rămăşiţe". La limită, prin descompuneri, din relaţia universală (iniţială) este posibil să nu rămână decât atributele cheie. Acum, însă, orice pericol privind nulitatea vreunui atribut cheie va atrage după sine eliminarea atributului respectiv sau, la limită, a relaţiei respective. Relaţia BIBLIOTECĂ_3 prezintă, dependenţe parţiale şi, astfel, constituie un bun „obiect" de normalizare în 2NF. De altminteri, relaţia abundă în redundanţe şi anomalii de genul: a) înregistrarea recepţiei unui titlu, introducerea datelor despre o carte (titlu) sunt imposibile până în momentul în care măcar o carte primeşte cotă; b) dacă un titlu a fost introdus iniţial eronat, corecţia trebuie operată pe destule linii ale tabelei; c) la fiecare achiziţie ulterioară a aceleiaşi cărţi (ISBN) trebuie introduse din nou ISBN-ul, titlul, editura etc. 38

Parcurgem cei 6 paşi, după cum urmează : 1. Cheia primară a relaţie iniţiale este: (Cota, Autor, CuvantCheie). 2. Ansamblul DF: (1)-(15) 3. În dependenţele (6)-(10), atributul Cota, component al cheii relaţiei, este sursă simplă. 4. Se constituie o relaţie în care cota este cheie primară, iar celelalte atribute sunt destinaţiile dependenţelor (6), (7), (8). (9) şi (10). 5. Din relaţia iniţială se elimină toate atributele destinaţie preluate în proaspăta tabelă, rămânând doar atributele cheie : (Cota, Autor, CuvântCheie); 6. Nici unul dintre cele trei atribute de la punctul 5 nu periclitează restricţia de entitate, aşa încât relaţia - „rămăşiţă" se păstrează în această formă. Prin urmare, în a doua formă normalizată, relaţia iniţială (universală) s-ar putea descompune în: CĂRŢI (Cota. ISBN,Titlu,Editura, LocSediuEd, AnApariţie) si TITLURI_AUTORI_CUVINTECHEIE (Cota. Autor. CuvântCheie) Conţinutul acestor două noi relaţii este prezentat în figura de mai jos.

CĂRŢI
Cotă ISBN Titlu Visual FoxPro. Ghidul dezvoltării aplicaţiilor profesionale Visual FoxPro. Ghidul dezvoltării aplicaţiilor profesionale Visual FoxPro. Ghidul dezvoltării aplicaţiilor profesionale SQL. Dialecte DB2, Oracle şi Visual FoxPro SQL. Dialecte DB2, Oracle şi Visual FoxPro (fragment) CuvântCheie baze de date SQL proceduri stocate FoxPro Formulare orientare pe obiect client-server Web Editura Polirom Polirom Polirom Polirom Polirom LocSediuEd laşi laşi laşi laşi laşi III-13421 973-683-8897 III-13422 973-683-8897 III-13423 973-683-8897 III-10678 973-683-7092 III-10679 973-683-7092 AnApariţie 2002 2002 2002 2001 2001

TITLURI_AUTORI_CUVINTECHEIE Cota Autor III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache III -13421 Marin Fotache ………………….

Figura 3.8. Relaţia BIBLIOTECA_3 în 2NF

39

3.6. A treia formă normalizată -3NF şi forma normală Boyce-Codd - BCNF
A treia formă normalizată (3NF) este considerată de mulţi specialişti drept un minimum acceptabil pentru structura unei baze de date relaţionale. Bazată pe a doua formă normală şi pe dependenţele funcţionale tranzitive (de fapt, pe eliminarea lor), 3NF a cunoscut două definiţii majore, una „originală", formulată de Codd însuşi şi a doua ce acoperă câteva lipsuri ale primei, numită, după autorii săi, Boyce-Codd Normai Form, în traducere oarecum liberă forma normală Boyce-Codd, mai pe româneşte, BCNF. Dependenţe funcţionale directe/tranzitive O dependenţă funcţională Datăl -> Dată2 este directă atunci când nu există o Dată3 care angajează o dependenţă funcţională tranzitivă de genul: Datăl -> Dată3 -> Dată2. Formal, dacă Ai —> Aj şi Aj-> Ak, atunci Ai—> Ak şi se notează: Ai —> Aj —> Ak Pentru relaţia BIBLIOTECĂ_TUPLURI_NOI_SOLUŢIA_2 dependenţele (7), (8), (9) şi (10) din paragraful 4.5.1.1. sunt tranzitive, deoarece: Cota -> ISBN -> Titlu Cota -> ISBN -> Editura Cota -> ISBN -> LocSediuEd Cota -> ISBN -> AnApariţie In plus, şi DF (13) este tranzitivă, întrucât: ISBN -> Editura -> LocSediuEd Pe baza noţiunilor prezentate, se poate defini închiderea tranzitivă a unui ansamblu de dependenţe funcţionale. închiderea tranzitivă reprezintă ansamblul dependenţelor totale directe + dependenţele totale tranzitive. Acoperirea minimală, definită în capitolul anterior, este subansamblul minimal de dependenţe funcţionale elementare care permit determinarea tuturor celorlalte dependenţe funcţionale. Cu alte cuvinte: (1) nici o dependenţă funcţională nu este redundantă şi (2) orice dependenţă funcţională totală face parte din închiderea tranzitivă. Spre deosebire de ceea ce am discutat în capitolul anterior, acum suntem în măsură să eliminăm din ansamblul DF şi pe cele tranzitive. Astfel, pentru relaţia BIBLIOTECĂ_3, acoperirea minimală este alcătuită din cinci DF: 40

- Cota -> ISBN - ISBN -> Titlu - ISBN -> Editura - ISBN -> AnApariţie - Editura -> LocSediuEd iar închiderea tranzitivă este următorul ansamblu de dependenţe: - Cota -> ISBN - Cota -> Titlu - Cota -> Editura - Cota -> LocSediuEd - Cota -> AnApariţie - ISBN -> Titlu - ISBN -> Editura - ISBN -> LocSediuEd - ISBN -> AnApariţie - Editura -> LocSediuEd Acoperirea minimală poate fi uşor reprezentată prin graful DF. Dependenţele tranzitive sunt foarte uşor de identificat şi eliminat. Spre exemplu, dacă din figura 3.6. eliminăm săgeţile ce reprezintă drumul direct dintre două atribute/grupuri şi un atribut destinaţie, atât timp cât între respectivele atribute/conectori există un „traseu ocolitor", se obţine graful acoperirii minimale vezi figura 3.9. Cota Autor CuvantCheie

ISBN

Editura

Titlu

AnApariţie

LocSediuEd

Figura 3.9. Graful DF de acoperire minimală pentru relaţia BIBLIOTECĂ_3 41

Atributele Autor şi CuvantCheie atârnă inutil în figură, stricând imaginea grafului. Le-am păstrat însă pentru a nu omite nici un atribut din relaţia universală şi a indica cheia primară a relaţiei.

Aducerea relaţiilor ȋn a treia formă normală Prima definiţie a celei de-a treia forme normale a unei relaţii poate fi formulată relativ simplu şi incremental, prin raportare la 2NF. O relaţie se află în 3NF dacă: 1. Se găseşte în 2NF. 2. Toate atributele care nu aparţin cheii primare nu depind funcţional de un alt atribut (ansamblu de atribute) care nu face parte din cheie. A doua condiţie poate fi exprimată si în maniera: toate dependenţele funcţionale care leagă cheia primara de celelalte atribute sunt directe (netranzitive). Trecerea din 2NF în 3NF presupune eliminarea DF tranzitive şi se poate face, pentru o relaţie, în următoarea manieră: a) Se identifică toate atributele ce nu fac parte din cheie şi sunt surse ale unor dependenţe funcţionale. b) Pentru toate atributele identificate la punctul a se constituie cate o relație in care cheie primara va fii atributul respectiv, iar celelalte atribute, destinațiile din dependentele considerate. Operațiile a si b se repeta pentru relațiile nou obținute prin decompoziție. De fiecare data din relațiile supuse descompunerii se elimina atributele destinație ale surselor non-cheie, păstrându-se atributele sursa , in vederea stabilirii legăturilor intre tabele si , implicit declarării restricțiilor referențiale. Relaţia BIBLIOTECĂ_3 a fost adusă în 2NF în fig.3.8 prin ruperea sa în CĂRŢI (Cota. ISBN,Titlu,Editura, LocSediuEd, AnApariţie) si TITLURI_AUTORI_CUVINTECHEIE (Cota. Autor. CuvântCheie) Cea de-a doua este alcătuită exclusiv din atribute cheie, deci nu se pune în discuţie 3NF (adică relaţia este deja în 3NF). Altfel stau lucrurile în CĂRŢI. Relaţia este în 2NF şi conţine dependenţe tranzitive. Există două atribute din afara cheii primare, ISBN şi Editura, care sunt

42

surse de DF, astfel încât dependenţele (7), (8), (9), (10) şi (13) sunt tranzitive. Trecerea în 3NF se realizează prin constituirea a două relaţii pe care o să le numim EDITURI şi TITLURI: EDITURI (Editura, LocSediuEd) si TITLURI (ISBN. Titlu, Editura, AnApariţie) iar din CĂRŢI rămâne: EXEMPLARE (Cota. ISBN) În concluzie, în 3NF, baza de date BIBLIOTECĂ este alcătuită din patru tabele: EDITURI (Editura. LocSediuEd) TITLURI (ISBN. Titlu, Editura, AnApariţie) EXEMPLARE (Cota, ISBN) TITLURI_AUTORI_CUVINTECHEIE (Autor, CuvântCheie ) Din păcate, ne rămâne pe conştiinţă ultima tabelă, TITLURI_AUTORI_CUVINTECHEIE, care conţine un grad ridicat de redundanţă a datelor, problemă rezolvată pe baza unui alt tip de dependente - mulţi valoare. Forma normală Boyce-Codd Definirea celei de-a treia forme normale, aşa cum a fost formulată iniţial de Codd, ridica o serie de probleme în anumite circumstanţe, probleme pe care formularea din acest paragraf le rezolvă. Chris Date este de părere că situaţiile în care definiţia originală a 3NF este insuficientă se traduc prin trei condiţii simultane: • relaţia are mai multe chei candidate; • o parte dintre cheile candidate sunt compuse; • cheile compuse au atribute în comun. Întrucât îndeplinirea simultană a celor trei condiţii se întâlneşte destul de rar în practică, a treia formă normală, aşa cum a fost formulată în paragraful precedent, este suficientă. Se spune despre o relaţie că este în forma normală Boyce-Codd (BCNF) dacă: 1. se află deja în 3NF; 2. nu există nici o DF a cărei sursă să fie un atribut necomponent al cheii, iar destinaţia, un atribut din cheie. Intr-o altă formulare, o relaţie R este în BCNF dacă şi numai dacă orice determinant (sursă de dependenţă funcţională sau supercheie) este o cheie candidată. Această exprimare are şi avantajul de a nu lega BCNF de 3NF, unii autori preferând să discute problema normalizării direct în termenii BCNF, fără a trece prin formele intermediare. 43

In cazul relatiei BIBLIOTECĂ_TUPLURI_ NOI_SOLUŢTA_2 combinaţia care diferenţiază orice linie de toate celelalte este(Cota, Autor, Cuvȋntcheie). Intuim însă un aspect pe care dependențele şi, implicit, normalizarea il scapă, şi anume că autorii şi cuvintele-cheie se referă la o carte (adică ISBN), şi nu la un exemplar fizic din depozit (Cota). Atunci, in schema bazei de date în 3NF se schimbă ultima tabelă, TITLURI_AUTORI_CUVINTECHEIE2 (ISBN, Autor, Cuvântcheie). Se observă cu ochiul liber o diminuare a volumului ultimei tabele. Rămâne, în schimb, un grad de redundantă chiar şi în forma „comprimată” a tabelei. Putem încerca să adăugăm în BIBLIOTECĂ_3 câteva atribute care să atragă în dependenţe atributele Autor şi CuvântCheie. Astfel, pornim de la faptul că, pe coperta unei cărţi, autorii sunt trecuţi într-o anumită ordine, deloc întâmplătoare, iar la extragerea informaţiilor despre cărţi această ordine trebuie respectată. Prin urmare, folosim atributul OrdineCopertă, iar DF este: (ISBN, OrdineCopertă) -> Autor De asemenea, pentru a putea extrage cărţile legate de unul sau mai multe cuvinte-cheie în ordinea relevanţei, introducem atributul Relevanţă, ce indică nivelul la care este tratată într-o carte o anumită noţiune/sintagmă (cuvânt-cheie): (ISBN, CuvântCheie) -> Relevanţă Pe baza acestor două noi dependenţe, relaţiile construite sunt aproape impecabile: EDITURI (Editura, LocSediuEd) CĂRŢI (ISBN, Titlu, AnApariţie, Editură) AUTORI_CARTI (ISBN, OrdineCoperta, Autor); CARTI_CUVINTE CHEIE (ISBN, CuvinteCheie, Relevanta); EXEMPLARE_CARTI (Cota, ISBN).

3.7.A patra formă normală - 4NF
Cu toate că BCNF elimină toate anomaliile datorate dependenţelor funcţionale, mai există un tip de dependenţă, numită dependenţă multivalorică, ce poate cauza probleme de redundanţă a datelor. Posibila existenţă a dependenţelor multivalorice în cadrul unei relaţii se datorează primei forme normale 1NF care nu permite unui atribut dintr-un rând să aibă o mulţime de valori. De 44

exemplu, dacă într-o relaţie există două atribute multivalorice, trebuie să repetăm fiecare valoare a unuia din atribute împreună cu fiecare valoare a celuilalt, dar efectul este apariţia redundanţei datelor. O relaţie este în 4NF dacă şi numai dacă: 1. este în BCNF; 2. toate dependenţele care se manifestă în cadrul său sunt dependenţe funcţionale, altfel spus, eventualele dependenţe multivaloare conţinute sunt, de fapt, dependenţe funcţionale. Este o formă mai strictă decât BCNF pentru că împiedică relaţiile să conţină dependenţe multivalorice, prevenind astfel redundanţa datelor. Relaţia BIBLIOTECĂ_3, după cum am văzut in paragraful precedent, conţine o dependentă multivaloare prin eliminarea căreia vom aduce relaţia în 4NF. Se va constitui câte o relaţie pentru fiecare sursă de dependenţă funcţională (Cota, ISBN şi Editura). La aceste relaţii se va adăuga câte o relaţie pentru fiecare destinaţie de dependenţă multivaloare (Autor şi CuvântCheie). Schema finală a bazei de date, precum şi conţinutul relaţiilor sunt ilustrate mai jos.

EDITURI EDITURA Polirom TITLURI ISBN

LocSediu Iasi

973-683-889-7 973-683-709-2 EXEMPLARE Cota III-13421 III-13422 III-13423 III-10678

Titlu Visual FoxPro. Ghidul dezvoltarii aplicatilor profesionale SQL. DialecteDB2, Oracle si Visual FoxPro

Editura AnAparitie Polirom Polirom 2002 2001

ISBN

973-683-889-7 973-683-889-7 973-683-889-7 973-683-709-2

TITLURI_AUTORI ISBN Autor 973-683-8897 Marin Fotache 973-683-8897 Ioan Brava 973-683-8897 Catalin Strambei 973-683-8897 Liviu Cretu 45

III10679

973-683-709-2

973-683-7092

Marin Fotache

TITLURI_CUVINTECHEIE ISBN CuvantCheie 973-683-889-7 baze de date 973-683-889-7 SQL 973-683-889-7 proceduri stocate 973-683-889-7 FoxPro 973-683-889-7 formulare 973-683-889-7 orientare pe obiect 973-683-889-7 client_server 973-683-889-7 web 973-683-709-2 baze de date 973-683-709-2 algebra relationala 973-683-709-2 SQL Fig.34.10. Relatia BIBLIOTECA forma finala

3.8. A cincea formă normală – 5NF
Cea de-a cincea formă normală - denumită şi forma normală proiecţie-joncţiune ProjectJoin Normal Form) - are la bază dependenţa de joncţiune şi a fost definită de Ronald Fagin: o relaţie R este în 5NF dacă şi numai dacă toate dependenţele de joncţiune sunt consecinţe ale cheilor candidate ale lui R. De remarcat că 5NF, 4NF şi BCNF corespund definiţiei unice: orice determinant al unei dependenţe este o cheie; ceea ce diferă ţine de faptul că pentru BCNF este vorba de dependenţă funcţională, pentru 4NF - dependenţă multivaloare, iar pentru 5NF - dependenţă de joncţiune. 5NF este o generalizare a 4NF, care este o generalizare a BCNF. Până la 5NF, o relaţie era descompusă prin proiecţie în două relaţii ce puteau, prin joncţiune naturala, să „refacă" in orice moment relaţia iniţială. Cu dependenţa de joncţiune, această descompunere fără pierderi poate fi generalizată nu la două, ci la mai multe relaţii. În fapt, dependenţa de joncţiune corespunde existenţei mai multor legături care sunt independente în cadrul relaţiei şi care vor fi izolate prin descompunerea în 5NF. 46

4. Crearea bazei de date cu ajutorul limbajului SQL
4.1. Fundamente limbaj SQL Limbajul SQL (Structured Query Language) este limbajul utilizat de majoritatea sistemelor de baze de date relaţionale (SGBDR) pentru definirea şi manipularea datelor. Majoritatea limbajelor posedă un set de instrucţiuni comun unanim acceptat de toate marile companii producătoare de soft, precum MICROSOFT sau ORACLE. Termenii utilizaţi de limbajul SQL sunt: -

tabel (Table) utilizat pentru a desemna o relaţie; linie (row) utilizat pentru a desemna un tuplu; coloană (column) utilizat pentru a desemna un atribut. componenta de descriere a datelor relaţionale (limbajul de descriere a datelor - LDD), componenta de manipulare a datelor relaţionale (limbajul de manipulare a datelor LMD), ambele fiind absolut necesare în gestiunea BD.

Componentele pe care le cuprinde limbajul SQL sunt următoarele:

47

Pe lângă aceste componente principale, standardul SQL2 mai prevede şi alte componente ale limbajului:
-

controlul tranzacţiilor; controlul securităţii şi refacerea datelor.

Controlul tranzacţiilor conţine comenzi pentru specificarea tranzacţiilor. Unele implementări adaugă comenzilor prevăzute în standard şi alte comenzi suplimentare de control al concurenţei şi refacerea datelor. Controlul securităţii şi refacerea datelor conţine comenzi de administrare a bazei de date pentru definirea utilizatorilor şi a drepturilor acestora de acces la tabele. Această componentă este dependentă de SGBD, iar pentru sisteme performante, administratorul BD este obiectul activităţii unei categorii speciale de utilizatori ai BD – administratori ai BD. Structura lexicală a limbajului SQL Elementele unei instrucţiuni (statement) sunt:
-

cuvintele cheie (key words), dintre care fac parte comenzile (SELECT, UPDATE, INSERT etc), operatorii (AND, OR, NOT, LIKE), clauzele (WHERE, SET, VALUES etc);

-

identificatorii (identifier) sunt elementele care denumesc tabela, atributul sau alt obiect BD; SQL face diferenţa între literele mari şi mici, deci este „case-sensitive”; identificatorul care conţine ghilimele se numeşte identificator delimitat;

-

constantele (literal) reprezintă şiruri de caractere (‘ ‘), numere întregi, numere reale (ex. 3.5; 4. ; .001; 5e2), constanta NULL care simbolizează lipsa de informare, constante de tip logic (1 pentru TRUE şi 0 pentru FALSE);

-

caracterele speciale, cum ar fi ; care semnifică terminarea comenzilor, . care semnifică virgula zecimală, sau * care simbolizează operatorul de înmulţire.

Operatori SQL SQL are următorii operatori:
-

operatori aritmetici binari: + (sumă), - (diferenţă), * (produs), / (împărţire), % (modulo), & (AND orientat pe biţi), | (OR orientat pe biţi), # (XOR orientat pe biţi), << (deplasare la stânga), >> (deplasare la dreapta).

-

operatori binari de comparaţie: < (mai mic), > (mai mare), <= (mai mic sau egal), >= (mai mare sau egal), = (egal), <> (diferit) sau != (diferit). 48

-

operatori de comparaţie: x BETWEEN min AND max verifică dacă min ≤ x ≤ max), x IN (v1,...,vn) compară x cu o listă de valori, x IS NULL, x IS NOT NULL, x LIKE model_şir.

-

operatori logici. Operatorii logici sunt legaţi prin cuvintele cheie AND, OR, NOT şi ei returnează una dintre valorile logice TRUE, FALSE sau NULL. operatori relaţionali: UNION (reuniune), INTERSECT (intersecţie), MINUS (diferenţă).

-

Funcţii definite în SQL Funcţii agregat Funcţiile agregat calculează un rezultat din mai multe tupluri ale unui tabel (funcţii de totalizare): COUNT - furnizează numărul de tupluri ale unui rezultat; SUM - execută suma tuturor valorilor dintr-un câmp; MAX - returnează valoarea cea mai mare dintr-un câmp; MIN - returnează valoarea cea mai mică dintr-un câmp; AVG - calculează media valorilor dintr-un câmp. Aceste funcţii vor fi folosite în instrucţiunea SELECT. Funcţii scalare Funcţiile scalare primesc unul sau mai multe argumente şi returnează valoarea calculată sau NULL în caz de eroare. Argumentele funcţiilor pot fi constante sau valori ale atributelor specificate prin numele atributelor corespunzătoare. Dintre funcţiile scalare amintim: funcţii numerice de calcul trigonometric: sin, cos, tan, cot etc. de calcul al logaritmului: ln, log, lg de calcul al puterilor: pow valoarea absolută: abs de rotunjire: floor, ceil etc. funcţii pentru manipularea şirurilor de caractere funcţii pentru data calendaristică funcţii de conversie

49

Tipuri de date În limbajul SQL sunt definite mai multe tipuri de date: numeric, şir de caractere, şir de biţi, data (calendaristică), timp. Denumirile tipurilor de date precum şi limitele acestora diferă de la un SGBD la altul, dar în general, sunt destul de asemănătoare. Tipul numeric include numere întregi: INTEGER sau INT reprezentat pe 4 octeţi; SMALLINT reprezentat pe 2 octeţi; numere reale reprezentate în virgulă flotantă, cu diferite precizii: FLOAT reprezentat pe 4 octeţi; REAL reprezentat pe 8 octeţi; DOUBLE [PRECISION] reprezentat pe 8 octeţi; numere zecimale reprezentate cu precizia dorită: tipul NUMERIC sau DECIMAL, cu forma numeric[(p,s)], unde p este numărul total de cifre afişate, iar s este numărul de cifre după punctul zecimal. Tipul şir de caractere CHARACTER (n) sau CHAR (n) definesc şiruri de caractere cu lungimea fixă. CHARACTER VARYING sau VARCHAR (n) defineşte şirul de caractere cu lungimea variabilă. Asemănarea dintre cele două tipuri prezentate mai sus este aceea că ambele reprezintă şiruri de maxim n caractere, iar deosebirea este aceea că pentru şiruri cu număr de caractere mai mic ca n, CHAR (n) completează şirul cu spaţii albe până la n caractere, iar VARCHAR (n) memorează numai atâtea caractere câte are şirul dat. Tipul şiruri de biţi BIT (n) defineşte secvenţe de cifre binare (care pot lua valoarea 0 sau 1) de lungime finită n; BIT VARYING (n) defineşte secvenţe de lungime variabilă, cu limita maximă n.

Tipuri pentru data calendaristică şi timp DATE permite memorarea datelor calendaristice în formatul yyyy-mm-dd; 50

TIME permite memorarea timpului, folosind trei câmpuri hh:mm:ss; TIMESTAMP(p) permite memorarea combinată a datei calendaristice şi a timpului, cu precizia p pentru câmpul SECOND (al secundelor); valoarea implicită a lui p este 6; INTERVAL este utilizat pentru memorarea intervalelor de timp. Tipurile de date sunt „case-insensitive”, deci nu ţin cont de caracterele mari sau mici. Limbaje relaţionale de definire a datelor (LDD) Limbajul de definire a datelor (a schemei unei BD) include instrucţiuni ce permit:
-

crearea schemei bazei de date; adăugarea relaţiilor la schema bazei; ştergerea unor relaţii existente; adăugarea de noi atribute relaţiilor existente; optimizarea bazei de date (index, grup, declanşator); definirea structurii fizice şi logice a unei BD; restricţii cu privire la utilizarea structurii de mai sus.

-

Comenzi pentru crearea unei baze de date Comanda pentru crearea unei baze de date este CREATE DATABASE nume_baza; Să se creeze baza de date BIBLIOTECA CREATE DATABASE BIBLIOTECA; Această comandă creează o BD cu numele nume_baza. Nu toate SGBDR suportă noţiunea explicită de BD, deşi utilizarea unei asemenea noţiuni poate facilita controlul drepturilor de acces la relaţiile BD. Utilizatorul care a creat baza de date devine automat administratorul BD. Comenzi pentru suprimarea unei baze de date Comanda pentru suprimarea unei baze de date este DROP DATABASE nume_baza; Această comandă distruge BD cu numele nume_baza.

51

Comenzi pentru crearea relaţiilor de bază În cadrul acestor comenzi se precizează numele relaţiei precum şi numele şi tipul atributelor. În SQL, cele mai frecvente tipuri de date sunt: CHAR - pentru şir de caractere de lungime fixă; VARCHAR2 - pentru şir de caractere de lungime variabilă; NUMBER - pentru numere întregi sau reale de lungime variabilă; DATE - pentru date calendaristice; LONG - pentru texte de lungime variabilă; RAW - pentru informaţie binară de lungime variabilă. Comanda de creare a unei relaţii este CERATE TABLE nume_tabela (atribute); Crearea unei relaţii indicând cheia la nivel de atribut Să se creeze relaţia EDITURI (simbol_județ, nume_județ). CREATE TABLE EDITURI (ID_edituraNUMERIC(8) PRIMARY KEY, Nume_editura VARCHAR(30)); Crearea unei relaţii indicând cheile la nivel de tabel Să se creeze relaţia TITLURI (ISBN, ID_editura, Titlu). CREATE TABLE TITLURI (ISBN NUMERIC (20) ID_editura NUMERIC(8), Titlu VARCHAR (30), PRIMARY KEY (ISBN, ID_editura), FOREIGN KEY (ID_editura) REFERENCES EDITURI(ID_editura)); Comenzi pentru suprimarea unei relaţii de bază Comanda de suprimarea unei relaţii este DROP TABLE nume_tabela; Comanda SQL distruge relaţia nume_tabela. 52

Comenzi pentru schimbarea numelui unei relaţii Comanda SQL pentru schimbarea numelui unei relaţii este RENAME TABLE nume_tabela TO nume_tabela_nou; Să se modifice numele relaţiei TITLURI_CUV_CHEIE în TITLURI_CUVCHEIE apoi să se suprime relaţia TITLURI_CUVCHEIE RENAME TABLE TITLURI_CUV_CHEIE TO TITLURI_CUVCHEIE; DROP TABLE TITLURI_CUVCHEIE; Comenzi pentru declararea restricţiilor de integritate (a constrângerilor) Constrângere este un mecanism care asigură că valorile unui atribut sau a unei mulţimi de atribute satisfac o condiţie declarată. Unei constrângeri i se poate da un nume unic. Dacă nu se specifică un nume explicit atunci sistemul automat îi atribuie un nume de forma SYS_Cn, unde n reprezintă numărul constrângerii. Constrângerile pot fi şterse, pot fi adăugate, pot fi activate sau dezactivate, dar nu pot fi modificate. Prin comanda CREATE TABLE pot fi specificate anumite restricţii (constrângeri) prin care se exprimă o condiţie care trebuie respectată de toate tuplurile uneia sau mai multor relaţii. Acestea pot fi definite cu ajutorul comenzii: ALTER TABLE Constrângerile declarative pot fi:
-

constrângeri de domeniu, care definesc valorile luate de un atribut: DEFAULT, NOT NULL, UNIQUE, CHECK; constrângeri de integritate a entităţii care precizează cheia primară: constrângeri de integritate referenţială care asigură corespondenţa între cheile primare şi cheile externe corespunzătoare: FOREIGN KEY.

-

PRIMARY KEY;

Fiecărei restricţii i se poate da un nume, lucru util atunci când, la un moment dat (salvări, restaurări, încărcarea BD) se doreşte dezactivarea uneia sau mai multora dintre acestea. Astfel se prefigurează numele fiecărei restricţii cu tipul său: pk_(PRIMARY KEY) pentru cheile primare un_(UNIQUE) pentru cheile alternative nn_(NOT NULL) pentru atributele obligatorii 53

ck_(CHECK) pentru reguli de validare la nivel de atribut fk_(FOREIGN KEY) pentru cheile străine. Să se realizeze constrângerea de cheie primară, de cheie externă şi constrângerea de domeniu pentru relaţia DESCRIERE_IMOBIL. CREATE TABLE DESCRIERE_IMOBIL (id_co SMALLINT (7) NOT NULL, CONSTRAINT FOREIGN KEY fk_co(id_co) REFERENCES CERERI_OFERTE(id_co), CONSTRAINT pk_co PRIMARY KEY (id_co), tip_imobil VARCHAR(10), etaj VARCHAR(10), nr_camere SMALLINT (6), suprafata DECIMAL (12,4), garaj TINYINT (4), centrala_termica TINYINT (4), termopane TINYINT (4)); Comenzi pentru modificarea structurii unei relaţii Prin modificarea structurii unei relaţii se înţelege: extinderea schemei relaţiei prin adăugarea de noi atribute; restrângerea schemei unei relaţii prin suprimarea unor atribute; modificarea numelui şi/sau tipului unui atribut din cadrul relaţiei.

Unele limbaje relaţionale (QBE) admit toate aceste tipuri de modificări în schema unei relaţii, iar altele (SQL sau QUEL) numai o parte. Comanda de modificare a unei relaţii este ALTER TABLE nume_tabel ... Adăugarea unui atribut cu ajutorul opţiunii ADD Să se adauge atributul „regiunea” în relaţia LOCALITATI. (Valorile acestui atribut vor fi: Transilvania, Banat, Oltenia, Muntenia, Moldova, Dobrogea.) ALTER TABLE LOCALITATI ADD (regiunea VARCHAR(10)); 54

Adăugarea unei constrângeri cu ajutorul opţiunii ADD Comanda pentru adăugarea unei restricţii este ALTER TABLE nume_tabela ADD CONSTRAINT ...; Exemplu: Să se adauge restricţia de cheie primară „nr_factura” pentru relaţia FACTURI. ALTER TABLE FACTURI ADD CONSTRAINT pk_nr_factura PRIMARY KEY (nr_factura); Comenzi pentru acordarea drepturilor de acces la baza de date La nivel logic, limbajele relaţionale oferă comenzi pentru acordarea drepturilor de acces la baza de date. Accesul unor persoane la BD se poate realiza doar în condiţiile recunoaşterii acestora de către sistem drept utilizatori autorizaţi. Creatorul unei relaţii primeşte în mod automat toate privilegiile de operare asupra acestei relaţii: căutări de date în relaţie actualizări ale datelor în relaţie actualizări ale schemei relaţiei ataşarea unor restricţii de integritate suprimarea relaţiei. Să se ofere utilizatorului cu numele Zita şi cu parola BDZ dreptul de conectare la BD, precum şi unele drepturi de acces la una dintre tabelele bazei de date. GRANT SELECT, UPDATE ON DESCRIERE_IMOBIL TO Zita IDENTIFIED BY 'BDZ'; Comenzi pentru retragerea drepturilor de acces la baza de date Comanda SQL pentru retragerea drepturilor de acces la BD este REVOKE UPDATE ON nume_tabela FROM nume_utilizator; Să se retragă drepturile utilizatorului Zita de actualizare a datelor. REVOKE UPDATE ON DESCRIERE_IMOBIL FROM Zita; Limbaje relaţionale de manipulare a datelor (LMD) Limbajele de manipulare a datelor trebuie să ofere o serie de facilităţi pentru prelucrarea datelor din relaţiile bazei de date şi anume: 55

GRANT SELECT, UPDATE ,... ON nume_tabela TO nume_utilizator;

-

interogări inserări modificări ştergeri.

Interogarea datelor Interogarea bazei de date reprezintă principala funcţie a unui limbaj relaţional de manipulare a datelor. Comanda fundamentală a standardului SQL este SELECT, aceasta permiţând interogarea unei baze de date. Interogarea reprezintă o întrebare care îşi extrage răspunsul din baza de date. Componentele interogării se numesc clause. Sintaxa generală a comenzii SELECT este următoarea: SELECT [ALL/DISTINCT/UNIQUE] listă de selecţie FROM listă de relaţii (tabele) WHERE condiţie de căutare asupra tuplurilor GROUP BY listă de atribute pentru partiţionarea HAVING condiţie asupra partiţiilor ORDER BY listă de atribute; Clauzele SELECT şi FROM sunt obligatorii. SELECT specifică datele care se selectează, iar clauza FROM specifică relaţiile din care se selectează. Restul clauzelor sunt opţionale. Să se selecteze toate persoanele împreună cu toate datele personale ale acestora existente în baza de date. SELECT * FROM DATE_PERSOANA; Interogarea datelor folosind operatorii IS şi IS NOT Să se selecteze numele tuturor persoanelor care nu au completată adresa de email, apoi să se afişeze numele tuturor persoanelor care au numărul de telefon completat. SELECT numele FROM DATE_PERSOANA WHERE email IS NULL; SELECT numele FROM DATE_PERSOANA WHERE nr_telefon IS NOT NULL; 56

Interogarea datelor folosind operatorii logici AND, OR, NOT Sintaxa pentru interogarea care utilizează un operator logic este condiţie 1 AND condiţie 2; condiţie1 OR condiţie 2; NOT condiţie; Să se determine numărul facturii şi codul numeric personal pentru ofertele soluţionate după date de 2006-05-01 şi cu un preţ final mai mare sau egal ca 100.000. SELECT cnp,nr_factura FROM FACTURI WHERE data_factura=’2006-08-01’ AND total>=’100000’; Interogarea datelor folosind operatorul LIKE Se cunosc mai multe modalităţi de utilizare a expresiei LIKE, şi anume: pentru o expresie care începe cu o anumită literă, de exemplu litera ‘A’: LIKE ‘A%’; pentru o expresie care se termină cu o anumită literă, de exemplu litera ‘A’: LIKE ‘%A’; pentru o expresie care include o anumită literă, de exemplu litera ‘A’: LIKE ‘%A%’; Să se selecteze numele, adresa şi emailul tuturor persoanelor feminine care au adresă de email pe yahoo sau personal. SELECT numele, adresa, email FROM DATE_PERSOANA WHERE adresa LIKE ‘%BAIA MARE%’ AND (email LIKE ‘%yahoo%’ OR email LIKE ’%personal%’); Interogarea datelor folosind operatorul BETWEEN Operatorul se utilizează în combinaţie cu două valori între care se află valoarea la care se referă operatorul. Sintaxa este val BETWEEN minim AND maxim; sau val>=min AND val<=max; Cele trei expresii val, min, max pot fi de tip numeric (numeric, decimal, int, smalint etc.), de tip dată calendaristică sau de tip caracter.

57

Să se selecteze codurile tuturor cererilor/ofertelor înregistrate în perioada 1 ianuarie 2006 şi 1 mai 20006. SELECT id_co FROM CERERI_OFERTE WHERE data_inreg BETWEEN ‘2006-01-01’ AND ‘2006-05-01’; Interogarea datelor folosind funcţiile calendaristice YEAR, DAY, MONTH Funcţiile YEAR, DAY, MONTH reţin dintr-un câmp de tip dată calendaristică anul, ziua, respectiv luna. Să se vizualizeze codurile tuturor cererilor/ofertelor înregistrate în luna mai. SELECT id_co FROM CERERI_OFERTE WHERE MONTH(data_inreg)=05; Interogarea datelor folosind ordonarea Datele se pot ordona după orice câmp. Ordonarea se poate face atât crescător cât şi descrescător. Sintaxa pentru interogarea ordonată crescător este : ORDER BY nume_câmp (ASC); ordonată descrescător este ORDER BY nume_câmp (DESC); Dacă ORDER BY nu este urmat de ASC sau DESC, ordonarea se face implicit crescător. Să se vizualizeze lista persoanelor în ordine alfabetică. SELECT numele FROM DATE_PERSOANA ORDER BY numele; Interogarea datelor din mai multe relaţii Interogarea datelor din mai multe relaţii este strâns legată de noţiunea de cheie primară, cheie secundară, restricţii de integritate, asocieri între relaţii. Să se afişeze ofertele şi denumirile oraşelor corespunzătoare ofertelor. SELECT id_co, nume_loc FROM CERERI_OFERTE, LOCALITATI WHERE CERERI_OFERTE.tipul=’oferta’ AND CERERI_OFERTE.cod_loc=LOCALITATI.cod_loc;

58

Clauza WHERE include condiţii care exprimă o egalitate între valorile identificatorului nume_câmp a relaţiei nume_tabel şi a celei ale referinţei la acest identificator în tabela referită. Atunci când în clauza FROM a unei comenzi SELECT apar mai multe tabele se realizează produsul cartezian al acestora. De aceea numărul de tupluri rezultat creşte considerabil, fiind necesară restricţionarea acestora cu o clauza WHERE. Atunci când este necesară obţinerea de informaţii din mai multe tabele se utilizează condiţii de joncţiune. În acest fel tuplurile dintr-un tabel pot fi puse în legătura cu cele din alt tabel conform valorilor comune ale unor atribute. Condiţiile de corelare utilizează de obicei atributele cheie primară şi cheie externă.

4.2. Crearea bazei de date BIBLIOTECA
Am analizat in capitolul anterior o baza de date Biblioteca. Am ajuns la concluzia ca pentru a functiona nu are nevoie decat de cinci tabele (EDITURI, TITLURI, TITLURI_AUTORI, TITLURI_CUVINTECHEIE, EXEMPLARE). Dar aceasta este o baza de date care se poate folosi numai pentru catalogarea si evidenta unor carti. Pentru un program mai amplu de evidentă a cărţilor dintr-o biblioteca de școala sau la o biblioteca municipala mai avem nevoie de câteva tabele. Tabele care sa ne tina evidenta cititorilor, ce cărţi au împrumutat, întârzieri in returnarea cărţilor, o carte de cate ori a fost împrumutata de pe raft , ….. Pentru aceasta am adăugat tabelele AUTORI, CUVINTE_CHEIE, IMPRUMUT , CITITORI si ADMINISTRARE. Intre tabelele AUTORI si TITLURI se produce o asociere de tip mulți la mulți deoarece, un autor poate scrie mai multe carti, iar o carte , poate avea mai mulți autori. Metoda clasica de rezolvare a acestui tip de conflict este construirea unei entitati intermediare care sa facă legătura intre cele doua tabele. Intre tabelele TITLURI si CUVINTE_CHEIE , se produce aceiași asociere de tip mulți la mulți deoarece un titlu se poate caracteriza prin mai multe cuvinte cheie , iar un cuvânt cheie 59

caracterizează mai multe titluri. Aceiași rezolvare ca mai sus , se interpune o entitate cu numele TITLURI_CUVINTE_CHEIE intre cele doua tabele. Pentru a gestiona cititorii care folosesc , împrumuta cartile din biblioteca noastre am introdus tabela CITITORI. In aceasta tabela am introdus atribute , care sa definească foarte bine un anumit cititor . CNP , Nr. permis, nume, prenume, locul nașterii, data nașterii sunt numai câteva din aceste atribute. In tabela IMPRUMUT găsim data de împrumut si data restituirii unei anumite carti, daca respectivul cititor a întârziat cu restituirea cartii si perioada care a întârziat. Tabela ADMINISTRARE conține atributele pentru autentificarea fiecărui utilizator ce accesează programul nostru.Diagrama E-R (entitate - relație) se poate vedea foarte bine in ANEXA 1. Se pot urmării legăturile dintre tabele , cheile primare , cheile străine, indexurile. Comenzile SQL pentru crearea bazei de date BIBLIOTECA se pot vedea in ANEXA 2.

5. Interfețele grafice in Java
Java este un limbaj de programare orientat obiect consacrat. Cele mai multe aplicaţii distribuite sunt scrise în Java, iar noile evoluţii tehnologice permit utilizarea sa şi pe dispozitive mobile gen telefon, agendă electronică, palmtop etc. In felul acesta se creează o platformă unică, la nivelul programatorului, deasupra unui mediu eterogen extrem de diversificat. Avantajele sunt evidente, atât pentru proiectanţi, care „scriu o dată şi execută pe orice maşină virtuală Java JVM), cât şi pentru utilizatori, care vor beneficia de un spectru îmbogăţit de servicii. De aceea se poate afirma cu încredere că Java este un câştigător, în lumea volatilă a tehnologiilor de calcul. Istoricul şi caracteristicile limbajului Java Java este un limbaj de programare orientat obiect, destinat în principal programării internet. Începutul limbajului Java este In toamna anului 1991, când firma Sun Microsystems a finanţat un proiect cu numele Green condus de James Gosling. Scopul echipei Green era sa plaseze firma Sun Microsystems pe piaţa produselor electronice comerciale. Inginerii şi dezvoltatorii de software de la Sun au căutat microprocesoare care sa ruleze pe o multitudine de maşini, în particular pe sisteme distribuite care lucrează în timp real. Cheia succesului firmei Sun a fost abilitatea lucrului pe platforme multiple. După patru ani de lucru, echipa Green finalizează 60

specificaţiile limbajului Java. Apoi, compania Sun Microsystems vinde licenţa firmelor IBM, Microsoft, Silicon Graphics, Adobe şi Netscape. Acum, Java e disponibil sub auspicii open source. Caracteristicile limbajului Java sunt: - limbaj compilat şi interpretat. Un limbaj este compilat dacă un program scris în acel limbaj este tradus într-un cod pe care calculatorul îl poate „înţelege" (executa) mult mai uşor. Un limbaj este interpretat dacă instrucţiunile unui program scris în acel limbaj sunt procesate linie cu linie. Programele interpretate sunt mai lente decât cele compilate, însă cele compilate sunt, de obicei, dependente de platforma respectivă. Programele Java sunt mai întâi compilate în nişte fişiere intermediare asemănătoare codului de asamblare (numite byte code, engl.), apoi acestea sunt interpretate de mediul de execuţie Java în instrucţiuni-maşină asociate platformei sistem. - limbaj independent de platforma. La instalarea limbajului Java, se va crea o maşină virtuală Java care are drept scop traducerea instrucţiunilor unui byte code Java în instrucţiuni-maşină pentru platforma curentă. Astfel fişierele intermediare byte code pot fi copiate şi executate pe orice platformă (indiferent dacă este Windows, Unix etc). Bineînţeles că nu trebuie să utilizăm elemente specifice unei platforme, cum ar fi delimitatorul utilizat în calea directoarelor:/ pentru Unix, respectiv \ pentru Windows (se vor utiliza în schimb constantele File.separatorChar sau File.separator). - limbaj orientat obiect. Cea mai importantă proprietate a limbajului Java este orientarea obiect, aceasta fiind privită ca o trăsătură implicită. Java pune în evidenţă toate aspectele legate de programarea orientată obiect: obiecte, trimitere de parametri, încapsulare, clase, biblioteci, moştenire şi modificatori de acces. - limbaj concurent. Concurenţa (engl. multithreading) înseamnă capacitatea unui program de a executa mai multe secvenţe de cod în acelaşi timp. O secvenţa de cod Java se numeşte fir de execuţie (engl. thread). Datorită posibilităţii creării mai multor fire de execuţie, un program Java poate să execute mai multe sarcini simultan, de exemplu, animaţia unei imagini, transmiterea unei melodii spre placa de sunet, comunicarea cu un server, alocarea şi eliberarea memoriei etc). - limbaj simplu. Spre deosebire de C++, care este cel mai popular limbaj orientat obiect, Java elimină câteva dintre trăsăturile acestuia: posibilitatea moştenirii multiple este exclusă, şirurile sunt încapsulate într-o structură clasă, Spre deosebire de C/C++ , în Java nu există

61

pointeri, iar alocarea şi dealocarea memoriei se fac automat. Există un mecanism de eliberare a memoriei (engl. garbage collection) pus în practică de un fir de execuţie de prioritate mică. - limbaj distribuit. Java este distribuit, deoarece permite utilizarea obiectelor locale şi de la distanţă. Limbajul Java oferă posibilitatea dezvoltării de aplicaţii pentru internet, capabile să ruleze pe platforme distribuite şi eterogene. în acest sens, Java respectă standardul IEEE (engl. Institute of Electricul and Electronics Engineers) pentru structurile de date, cum ar fi folosirea întregilor, a numerelor în virgulă flotantă şi a şirurilor de caractere. Java se poate utiliza în aplicaţii de reţea, deoarece respectă protocoalele de reţea, cum ar fi FTP, HTTP, SOAP etc. - limbaj performant. Interpretorul Java este capabil să execute un byte code aproape la fel de repede ca pe un cod compilat. Având posibilitatea să lucreze cu fire de execuţie multiple, Java justifică faptul că este un limbaj performant. De exemplu, un program Java poate aştepta citirea unor date, în timp ce un alt fir de execuţie poate aloca sau elibera memoria necesară programului. limbaj dinamic şi robust. Java întârzie alocarea obiectelor şi legarea dinamică a claselor până la momentul execuţiei. Astfel, se vor evita erorile de alocare chiar dacă mediul s-a schimbat de la ultima compilare a programului. Faptul că Java este robust se justifică prin eliminarea utilizării pointerilor, care era generatoare de erori în cazul programelor C / C + + . In schimb, Java verifică memoria dinamic înainte de a fi alocată şi are un sistem automat de alocare/dealocare a memoriei. -limbaj sigur. Programele Java nu pot accesa memoria heap, stack sau alte secţiuni protejate de memorie, deoarece Java nu foloseşte pointeri şi alocă memorie doar la execuţie. înainte ca interpretorul Java să execute byte code-ul se verifică dacă este un cod Java valid prin cercetarea accesului la date, a conversiilor de date nepermise, a valorilor şi parametrilor incorecţi, a depăşirii stivei. Instalare Limbajul Java se poate instala pe calculatoare cu diverse sisteme de operare, cum ar fi Windows, Linux, staţii Sun Solaris. Acest lucru este posibil, deoarece un program Java nu se execută direct de către microprocesor, ci utilizând un calculator ipotetic intermediar numit maşina virtuală Java (engl. Java Virtual Machine - JVM). Un compilator Java translatează codul-sursă Java într-un limbaj numit byte code (care e format din instrucţiuni-maşină pentru maşina virtuală Java) asemănător limbajului de asamblare şi pe care îl vom denumi cod binar Java. Pentru execuţia unui program Java, interpretorul Java inspectează şi decodifică codul binar Java, verifică dacă este sigur de executat şi apoi îl execută instrucţiune cu instrucţiune. La 62

instalarea limbajului Java, se creează, de fapt, corespondenţa dintre acţiunile codului binar Java şi instrucţiunile maşinii fizice. Acesta este „secretul" independenţei de platformă a limbajului Java. Faptul ca în procesul de traducere a codului-sursă Java in instrucţiunile maşinii fizice s-a interpus maşina virtuali Java implică o scădere a vitezei de execuţie faţă de un program echivalent care foloseşte instrucţiuni-maşină native. Dacă la începuturile limbajului Java un program era de 10 ori mai lent, în versiunile actuale* ale pachetului JDK (engl. Java Development Kit) performanţele au crescut semnificativ, raportul vitezei de execuţie dintre un program Java şi un program scris în cod nativ fiind de aproximativ 2. Mai mult, pentru un mediu Java care suportă compilarea în timpul încurcării (engl. Just-In-Time compilation) nu va exista nici o diferenţă de viteză a execuţiei, Compilatoarele Just-In-Time vor traduce programele Java în instrucţiuni-maşină native chiar din momentul încărcării. Sunt disponibile mai multe medii de dezvoltare a aplicaţiilor Java (JDK - Java Development Kit), realizate de diverşi producători printre care Sun, IBM, Borland. Firma Sun pune la dispoziţie gratuit kitul de instalare pentru sistemele de operare Windows, Linux şi Unix pe situl http://java.sun.com/. Pentru crearea şi editarea programelor Java se poate utiliza orice editor obişnuit de texte, însă este recomandată utilizarea unui mediu specializat întrucât acestea reduc semnificativ timpul de dezvoltare a aplicaţiilor. Cele mai importante medii de programare pentru Java sunt Eclipse - http://www.eclipse.org/, NetBeans - http://www.netbeans.org/ şi IntelliJ Idea - http://www.jetbrains.com/idea/. Pentru sistemul de operare Windows, instalarea kitului JDK 1.6.0 se realizează implicit în directorul C: \Program Files\ Java\ jdkl.6.0\ care va conţine subdirectoarele bin, demo, include, jre, lib şi sample. In subdirectorul bin se găsesc principalele instrumente ale pachetului JDK:
-

j a v a c . e x e - compilator Java; j a v a . e x e - interpretor Java; a p p l e t v i e w e r . e x e - instrument de vizualizat appleturi; j a v a d o c . e x e - generator de documetanţii; j a r . e x e - instrument pentru arhive jar; j a v a p . e x e - dezasamblor de fişiere byte code.

Tipuri de aplicaţii Java În principiu, există mai multe tipuri de aplicaţii Java:
a) aplicaţii de sine stătătoare (engl. stand-alone);

b) aplicaţii care se execută pe partea de client (numite appleturi); 63

c) aplicaţii care se execută pe partea de server (numite servleturi). a) O aplicaţie de sine, stătătoare Java este un program care poate fi executat în afara contextului unui browser (navigator) Web. Principala caracteristică a acestui tip de aplicaţie este încapsularea în cadrul clasei principale a unei funcţii main(), asemănătoare cu cea folosită în C, care are următoarea signatură: public static void main(String [] args) Aplicaţiile Java de sine stătătoare se pot împărţi la rândul lor în:
-

aplicaţii de consolă, care rulează la linia de comandă; de exemplu, fereastră de consolă (engl. command prompt) pe un calculator personal rulând Windows; aplicaţii-fereastră, care lucrează cu ferestre grafice folosind interfaţa grafica cu utilizatorul (engl. Graphical User Interface - GUI).

-

In continuare vom edita un text-sursă pe care îl vom salva în fişierul AplicatiaUnu.java ca aplicaţie de consolă. public class AplicatiaUnu { public static void main (String args[]) { if (args.length == 0) System.out.println("Aplicaţie independenta."); else { System.out.println("Argumentele programului sunt:”); for (int i = 0; i < args.length; i++) System.out.println(args[i]); } } Chiar dacă este un program simplu, acesta înglobează multe dintre trăsăturile unui program orientat obiect complex, şi anume: are un obiect (implicit generat de sistemul Java), utilizează încapsularea şi transmiterea parametrilor, defineşte o clasă, foloseşte moştenirea şi modificatori de acces. Compilarea acestui program Java se realizează cu comanda: javac AplicatiaUnu.java Astfel, se va crea fişierul în cod binar Java cu numele AplicatiaUnu.class execuţia acestui program se va realiza folosind în mod similar comanda: java AplicatiaUnu Pe ecran va apărea mesajul: Aplicaţie independenta. Este de remarcat faptul că la compilare trebuie scrisă şi extensia fişierului (. java), pe când la interpretare, aceasta nu trebuie specificată. 64

b) Aplicaţiile care se execută pe partea de client sunt cele încărcate de pe un server (de cele mai multe ori aflat la distanţă) şi apoi executate de programe speciale cum ar fi navigatoarele Web. De exemplu, appleturile sunt aplicaţii care sunt executate de către navigatorul Web, iar middleturile sunt executate de către dispozitive mobile fără fir (mai exact de către sistemul software al acestora). Un applet este un program Java respectând o mulţime de convenţii care îi permit să ruleze în cadrul unui navigator Web ce încorporează o maşină virtuală Java. Tehnologia appleturilor este similară, într-un anumit sens, cu a programelor JavaScript. Fişierul cu extensia . c l a s s al unui applet este stocat pe un server Web şi poate fi accesat de către un client prin intermediul unei pagini care conţine acel applet. La încărcarea paginii, codul appletului este transferat pe maşina-client şi v a fi executat cu ajutorul maşinii virtuale incluse în navigator. Fie textul-sursă Java memorat în fişierul AplicatiaDoi.java: import java.awt.Graphics; import java.applet.Applet; public class AplicatiaDoi extends Applet { public void paint(Graphics g) { g.drawString("Acesta este un applet", 50, 50); } } Compilarea acestui program Java se realizează astfel: javac A p l i c a t i a D o i . j a v a In acest mod se va crea fişierul byte code cu numele AplicaţiaDoi.class. c) O aplicaţie ce se execută pe partea de server este o aplicaţie care este rulata de către un server ca urmare a unei cereri primite de acesta, iar rezultatul este trimis programului solicitant. De cele mai multe ori acestea extind funcţionalitatea respectivului server. De exemplu, servleturile sunt aplicaţii care se execută pe partea de server. Un servlet este o componenta Web, scrisă în Java, care poate fi încărcata dinamic si rulată de un server Web, şi care poate interacţiona cu diferiţi clienţi folosind o implementare a paradigmei cerere/răspuns bazată pe protocolul HTTP. Servleturile extind funcţionalitatea unui server, de obicei, a unui server HTTP. Spre deosebire de appleturi, servleturile nu afişează o interfaţă grafică către client, ci doar rezultatul . Un caz particular de servleturi îl constituie JSP-urile (Java Server Page). Această tehnologie este atât o extensie a servleturilor, cât şi o extensie a limbajului HTML. Prin intermediul unor taguri particulare se pot insera declaraţii, expresii, secvenţe de cod Java etc. 65

Unele aplicaţii mai complexe au nevoie de o cantitate mare de informaţii structurate, iar pentru acest lucru se recurge la utilizarea bazelor de date. Conexiunile la baze de date se realizează în Java prin intermediul JDBC (Java Database Connection). JDBC este o specificare API (Application Programming Interface) dezvoltată de Sun care defineşte o interfaţă uniformă pentru accesarea diferitelor baze de date. JDBC este parte a platformei Java şi este inclusă în pachetul JDK. Cea mai importanta funcţie a JDBC-ului este posibilitatea lucrului cu instrucţiuni SQL (engl. Structured Query Language) şi procesarea rezultatelor într-o manieră independentă şi consistentă de bazele de date. JDBC furnizează acces orientat pe obiecte la bazele de date prin definirea de clase şi interfeţe care reprezintă obiecte, cum ar fi conexiuni la baze de date, instrucţiuni SQL, mulţimi-rezultat, obiecte binare şi şiruri de caractere de dimensiuni mari, drivere de baze de date, manageri de drivere. Aplicaţiile, fie de sine stătătoare, fie pe partea de client sau server, pot stabili conexiuni la baze de date, la diverse servere din reţea, pot salva starea obiectelor pentru a le restaura la o execuţie ulterioară sau pentru trimiterea în fluxuri de date. De asemenea, pot prelucra date în diferite formate: text (documente T X T , H T M L , XML, RTF etc.), grafic (2D şi 3D) şi video. Maşina virtuală Java Maşina virtuală Java este noutatea principală a limbajului Java faţă de celelalte limbaje de programare. Partea dificilă a creării codului binar Java este compilarea codului-sursă pentru o maşină care nu există fizic. Această maşină este numită maşina virtuală Java, deoarece există doar în memorie. Apoi, interpretorul Java traduce instrucţiunile cod-maşină Java în mulţimi de instrucţiuni care pot fi înţelese de maşina reală (fizică). Cele mai importante părţi ale unei astfel de maşini care necesită simularea unui calculator real sunt : o mulţime de regiştri, o stivă, un mediu de execuţie, un ansamblu pentru eliberarea memoriei, o tabelă (engl. pool) de literali constanţi, un spaţiu de memorie a unei metode şi o mulţime de instrucţiuni. Clase Clasa este entitatea de bază a unui limbaj orientat pe obiecte. In Java este obligatorie definirea a cel puţin unei clase. Nu este însă obligatorie crearea unei instanţe (unui obiect) a acelei clase, caz în care se vor utiliza date şi metode statice. O declaraţie de clasă în limbajul Java are sintaxa generală: [<ModificatoriClasa>] class <Identificator> [ <ListaTipuriReferinta>] [extends <NumeClasa>] 66

[implements <ListaInterfete>] { [<DeclaratiiCorpCl.asa>] } unde:
• • •

<ModificatoriClasa> pot fi: public, abstract, final (cel mult o apariţie şi, de preferat, în această ordine); <Identificator> reprezintă numele clasei; <ListaTipuriReferinta> este o listă de tipuri referinţă, numite şi tipuri generice, de forma: <TipReferintal>, <TipReferinta2>, ...,<TipReferintaN> şi este cuprinsă între simbolurile „<"şi „>".


• • • • •

<NumeClasa> este numele unei alte clase (denumită clasă de bază sau superclasa); <Lista Interfete> este o listă de nume de interfeţe de forma:
<NumeInterfaţa1>,<NumeInterfata2>,… , <NumeInterfataM>;

<DeclaraţiiCorpClasa> este o listă de declaraţii de forma: <DeclaratiiMembruClasa>, care, la rândul ei, poate fi <DeclaratieAtribut> sau <DeclaratieMetoda>; <InitializatorStatic>; <DeclaratiiConstructor>. Interfeţe O interfaţa grupează mai multe metode şi date membre publice. Sunt definite doar

prototipurile metodelor, implementările urmând a fi scrise în clasa care va implementa respectiva interfaţă. Gruparea metodelor publice este utilă pentru uniformizarea modalităţii de lucru cu anumite clase. Există şi interfeţe care nu posedă metode sau date membre, acestea având rol de indicator (engl. flag). O clasă poate implementa mai multe interfeţe, dar poate moşteni doar o singură clasă. Relaţia de moştenire este valabilă şi pentru interfeţe. Prin implementarea mai multor interfeţe se simulează moştenirea multiplă (întâlnită în alte limbaje de programare orientate obiect, cum ar fi limbajul C+ +). O declaraţie de interfaţă introduce un tip referinţă ai cărui membri sunt constante şi metode abstracte. Acest tip nu posedă implementări (metodele nu sunt definite), dar anumite

67

clase pot implementa aceste interfeţe furnizând definiţii pentru metodele abstracte. Sintaxa generală a declaraţiei unei interfeţe este: [publicc | abstract] interface <Identificator> [extends <ListaInterfete>] { [<DeclaratiiMembriInterfata>]
}

unde:
• • •

<Identificator> reprezintă numele interfeţei; <ListaInterfete> are forma generală: <Interfatal>,...<InterfataN>, unde <InterfataI> reprezintă identificatori (nume) de interfeţe, pentru I de la 1 la N; <DeclaratiiMembriInterfata> are forma generală: <DeclaratieMembrul>, …,<DeclaratieMembruK>,unde <DeclaratieMembruI>,pentru I de la 1 la K, poate fi: <DeclaratieConstanta> sau <DeclaratieMetodaAbstracta> Numele unei interfeţe (<Identificator>) nu poate coincide cu numele altei clase sau

interfeţe din acelaşi pachet, altfel apare eroare la compilare. Ca şi în cazul claselor, domeniul numelui unei interfeţe este întreg pachetul în care este declarat. Fiecare interfaţă este implicit abstractă, deci este inutil modificatorul a b s t r a c t în declaraţia unei interfeţe. Dacă declaraţia unei interfeţe conţine clauza extends, atunci interfaţa va moşteni toate metodele şi constantele interfeţelor enumerate în <ListaInterfete>, implementeze toate superinterfeţele accesibile clasei. Superinterfeţele din clauza extends trebuie să fie accesibile, altfel apare eroare la compilare. Nu există o superinterfaţă generală (pentru toate interfeţele), cum este clasa Object pentru superclase. care se numesc superinterfeţele directe. Orice clasă care implementează interfaţa declarată va trebui să

5.1.Initiere in SWING
Biblioteca Swing este partea JFC (engl. Java Foundation Classes) care oferă componentele necesare programatorilor pentru crearea de interfeţe grafice moderne, complexe si într-adevăr prietenoase aplicaţiilor Java. Swing aduce îmbunătățiri calitative faţa de mai vechiul pachet AWT (engl. Abstract Window Tbolkit), folosit în trecut pentru realizarea interfeţelor grafice, completându-i neajunsurile. Spre exemplu, in distribuţia AWT pentru Java 1.0, 68

programatorul avea la dispoziţie numai patru fonturi cu care putea să opereze şi un număr restrâns de tipuri de componente, insuficiente pentru crearea de interfeţe cu un grad ridicat de complexitate. Totuşi pachetul Swing nu este total separat de AWT cum s-ar putea crede, ci se poate spune că este construit peste acesta (engl. on top), AWT fiind folosit mai mult pe post de intermediar între Swing şi sistemul de operare peste care este instalată platforma Java. Printre îmbunătăţirile aduse de Swing, în afară de noile componente adăugate, putem enumera modul de prezentare şi comportare pentru interfaţă independentă de platformă, posibilitatea de a avea componente cu forme nerectangulare, accesibilitate pentru persoanele cu deficienţe etc. Acest pachet a fost astfel gândit, încât pentru lucruri simple este nevoie de scrierea de cod puţin, iar pentru lucruri mai complexe, mărimea codului creşte proporţional. De asemenea, se folosesc convenţii logice pentru denumirea claselor, metodelor etc. care, odată înţelese şi învăţate, determină creşterea vitezei de lucru. Despre interfeţe grafice Interfaţa cu utilizatorul, pe scurt UI (engl. User Inter/ace), reprezintă totalitatea mecanismelor care permit interacţiunea dintre o aplicaţie şi utilizatorii ei. O particularizare a interfeţei cu utilizatorul o reprezintă interfaţa grafică, pe scurt GUI (engl.Graphic User Interface) care se referi strict la comunicarea vizuală dintre utilizator şi aplicaţie. Putem spune că interfaţa grafică este locul de întâlnire dintre utilizatori şi aplicaţia care le este destinată. Deseori aplicaţiile sunt percepute de utilizatorii finali doar prin intermediul interfeţelor acestora şi, de aceea, o interfaţă realizată deficitar poate compromite întreaga aplicaţie, chiar dacă funcţional ea este bine realizată. In acest sens, o problemă în procesul de realizare a interfeţei grafice o reprezintă posibilitatea ca utilizatorul să nu înţeleagă cum să o utilizeze după ce a fost creată. Acest lucru se întâmplă mai ales pentru că, în general, utilizatorii unei aplicaţii (destinatarii aplicaţiei) nu sunt şi programatori, aceştia din urmă având intenţia de a crea interfaţa conform propriului model mental, diferit de cel al utilizatorilor. De aceea, dezvoltatorii aplicaţiei trebuie să intuiască modalităţile prin care utilizatorii modelează conceptual diferitele funcţionalităţi sau, în general, aspecte ale aplicaţiei, şi să încorporeze aceste modele în viitoarea interfaţă grafică. Metoda folosită în acest proces este analogia concretizată prin metaforă. Acolo unde analogiile sunt greu de realizat, sunt folosite idiomurile care reprezintă convenţii între creatorii şi utilizatorii interfeţei, uşor de reţinut de aceştia din urmă. Spre exemplu, funcţia de ştergere într-o aplicaţie poate fi mai uşor concepută de utilizatori ca aruncarea unui obiect nefolositor la coş. Astfel, pentru a şterge o pictogramă, utilizatorul îl trage deasupra coşului de 69

gunoi (engl. trash), reprezentat grafic de o altă pictogramă, unde îl eliberează. Acest mod de a vedea lucrurile poartă numele de „înglobarea semanticii în sintaxă", deoarece se încearcă o folosire a simbolurilor care sunt mai uşor de înţeles şi de reţinut. Un alt exemplu ar putea fi folosirea de pictograme în barele de unelte, care ascund printr-o reprezentare grafică uneltele ce se vor folosi după selectarea lor (spre exemplu, o lupă folosită mai apoi ca unealtă pentru realizarea operaţiei de micşorare-mărire). Se poate observa faptul că, în general, există un număr limitat de astfel de metafore şi simboluri care se repetă în mai toate aplicaţiile şi pe toate platformele. Din punctul de vedere al ingineriei programării, momentul în care se pune cu adevărat problema interfeţei cu utilizatorii este cel al procesului de proiectare arhitecturală a aplicaţiei, dar creatorii aplicaţiei vor face aprecieri chiar în procesul de analiză a cerinţelor utilizatorilor. Aşa cum se realizează un plan al produsului informatic, se recomandă realizarea planului interfeţei cu utilizatorul, prin care se clarifica modul cum va arăta interfaţa grafică înainte de a trece la implementarea efectivă a acesteia. JFC (Java Foundation Classes) JFC reprezintă un grup de API-uri (engl. Application Programming Interface) incluse în platforma J2SE (engl. Java 2 StandardEdition), care permit dezvoltatorilor sa creeze interfeţe grafice (GUI) pentru aplicaţiile Java. Java Foundation Classes constă in cinci pachete: AWT, Swing, Accessibility, Java 2D şi Drag and Drop, care se întrepătrund, neavând, în general, o existenţă de sine stătătoare. Java 2D a devenit o parte integrantă a AWT, Swing este construit peste AWT (se aşteaptă ca Swing să se îmbine mult mai puternic cu AWT în următoarele distribuţii Java), suportul Accessibility este construit în Swing, iar API-ul Drag and Drop este integrat în AWT şi Swing. Oferim în tabela care urmează o scurtă prezentare a celor cinci părţi componente ale JFC: Parte componentă a JFC AWT Explicatie Parte a JFC proiectată pentru a oferi suport pentru crearea interfeţelor grafice, folosind modul grafic. Oferă o ierarhie de clase suficiente pentru proiectarea unei interfeţe grafice nesofisticate pentru un applet sau o aplicaţie. Reprezintă nucleul JFC şi fundamentul pe care s-a construit pachetul Swing

70

Swing

Reprezintă un set vast de componente grafice, de la cele mai simple, cum ar fi etichetele sau butoanele, la cele mai complexe ca,de exemplu, tabelele sau arborii. Oferă independenţă faţă de platforma peste care este instalată maşina virtuală şi posibilitatea personalizării aspectului interfeţei şi a comportamentului acesteia la acţiunile utilizatorului. Reprezintă posibilitatea de a oferi ajutor utilizatorilor cu deficienţe, cum ar fi posibilitatea de a descifra interfaţa folosind mesaje vocale, Braille sau dispozitive exterioare ataşate calculatorului. Oferă informaţiile de care au nevoie programatorii care scriu software pentru astfel de dispozitive auxiliare sau look-and-feel-uri Pachetul javax. accessibility este cel care stă la baza acestui system. API-ul care permite utilizatorilor să încorporeze în aplicaţiile lor grafică 2D complexă, text şi imagini. Oferă posibilitatea de a realiza operaţii de drag-and-drop între aplicaţia curentă şi aplicaţiile native sau între două aplicaţii Java, La baza acestei facilităţi stau pachetele java.awt.dnd şi java.awt.datatransfer, dar, în general, nu este nevoie de folosirea lor de către programatori, deoarece sistemul drag-and-drop funcţionează implicit.

Accessibility

Java 2D Drag and Drop

Diferenţa majoră dintre Swing şi AWT este aceea că, spre deosebire de AWT, componentele Swing sunt scrise 100% în Java, neconţinând cod nativ (dependent de sistemul de operare). Aceasta înseamnă că butoanele Swing, spre exemplu, vor arăta şi se vor comporta identic pe platforme Macintosh, Solaris, Linux sau Windows. Spre deosebire de cele Swing, butoanele AWT luau mereu aspectul platformei pe care rula aplicaţia. De asemenea, prin această independenţă faţă de platformă se obţine o îmbunătăţire a vitezei de execuţie a aplicaţiilor având interfeţe realizate în Swing. API-ul JFC a fost perfecţionat şi optimizat pe măsura apariţiei de noi distribuţii ale platformei Java şi îl regăsim ca parte integrantă în platforma Java 2 Standard Edition. Unele clase şi metode s-au învechit şi s-a renunţat la folosirea lor efectivă pe parcursul apariţiei noilor distribuţii de platforme Java, din cauza ineficientei sau greşelilor pe care le conţineau. Componentele şi pachetele bibliotecii Swing Componentele Swing sunt aproape toate derivate dintr-o singură clasă de bază numită JComponent, care moşteneşte, la rândul ei clasa Container din AWT. Moştenirea clasei JComponent dă componentelor posibilitatea de a avea chenare, tooltips, respectiv look-and-feel configurabil. De asemenea, tot din JComponent se moştenesc şi metodele prin care se pot seta 71

dimensiunile şi poziţionarea componentelor. In general, fiecare componentă grafică din AWT are o clasă echivalentă în Swing, al cărei nume se formează din echivalentul AWT la care adăugăm prefixul J (singura excepţie este clasa Canvas). Reciproca nu este adevărată, deoarece Swing îmbogăţeşte considerabil paleta componentelor disponibile în AWT. O componentă grafică reprezintă un obiect care are o anumită reprezentare grafică ce poate fi afişată pe ecran şi poate astfel interacţiona cu utilizatorul. Reprezentări grafice au toate obiectele care sunt instanţe ale claselor derivate din java.awt.Component şi, în particular, javax.swing.JComponent pentru componentele Swing. Pentru a crea un buton având un anumit text drept conţinut, trebuie mai întâi să realizăm o instanţă a clasei JButton: JButton buton = new JButton("De acord"); Dacă dorim să creăm o listă de cuvinte din care utilizatorul să poată selecta un singur element la un moment dat, trebuie să realizăm mai întâi o instanţă a clasei JList, folosind unul dintre constructorii pe care această clasă îi pune la dispoziţie. String conţinut[]={"AWT", "Swing", "Accessibility", "Java 2D", "Drag and Drop"}; JList lista = new JList(conţinut); In acest caz, butonul şi lista reprezintă componente grafice, iar până aici modul de construcţie a componentelor nu diferă cu nimic de construcţia unui obiect obişnuit. Este de remarcat faptul, crearea obiectelor grafice nu determină şi afişarea reprezentării lor grafice pe ecran. Componentele trebuie să fie aşezate mai întâi pe o suprafaţă de lucru (care mai poartă denumirea de container), la anumite coordonate şi ocupând o anumită zonă a acesteia. Acest lucru se face prin intermediul unui apel al containerului de forma add (JComponent componenta). Trebuie înţeles faptul că nu se pot desena componente fără a fi adăugate iniţial unei suprafeţe de desenare reprezentate printr-un container de bază de tip JFrame, JDialog, JWindow sau JApplet. In continuare, vom adăuga o listă unei ferestre JFrame, care este una dintre componentele cu rol de container. import javax.swing.JFrame; import javax.swing.JList; /** O fereastra */ public class Fereastra extends JFrame { // constructorul clasei public Fereastra() { super("Fereastra") ; // cream o componenta String conţinut[] = { "AWT", "Swing", "Accessibility", "Java 2D", "Drag and Drop" }; 72

JList lista = new JList(conţinut) ; // adăugam componenta this.getContentPane().add(lista) ;
} După aşezarea în container, componentele grafice vor deveni vizibile doar odată cu vizualizarea întregii suprafeţe de desenare printr-un apel setVisible(true).

}

/** Aplicaţia pentru fereastra*/ public class Aplicaţia { public static void main(String[] args) { // cream fereastra Fereastra fereastra = new Fereastra(); // facem vizibila fereastra fereastra.pack() ; fereastra.setVisible(true); } } De asemenea, chiar dacă vizualizarea containerului a fost deja realizată, prin adăugarea unei noi componente containerului, aceasta va deveni, la rândul ei, vizibilă fără a mai fi nevoie de un apel setVisible ( ) . Folosind un apel de forma setVisible (false) aplicat unei componente deja vizualizate, aceasta se va ascunde. Dacă este un container conţinând şi alte componente, acestea vor fi la rândul lor ascunse. Modul în care componentele unui container vor fi desenate la momentul vizualizării acestuia depinde de gestionarul de poziţionare care este asociat containerului. Acesta determina cum vor fi poziţionate componentele pe suprafaţa de desenare şi ce dimensiuni vor avea. Gestionarii sunt instanţe ale claselor care implementează interfaţa LayoutManager, cum ar fi; BorderLayout, BoxLayout, CardLayout, FlowLayout, GridLayout, GridBagLayout sau SpringLayout. Interfaţa LayoutManager2 este derivată din LayoutManager şi este extinsă de cei mai mulţi dintre gestionarii enumeraţi mai sus, care oferă acestora suport pentru aliniamentul componentelor conţinute şi gestiunea dimensiunilor maxime. Prezentăm în continuare modalitatea prin care se ataşează un gestionar unui container. Spre exemplu, deoarece gestionarul BorderLayout, care este asociat implicit containerului ce ţine conţinutul unei ferestre, nu respectă dimensiunile asociate componentelor de către dezvoltator, îi vom asocia un alt gestionar de poziţionare folosind metoda setLayout ( ) . JPanel conţinut = this.getContentPane() ; conţinut.setLayout(new FlowLayout()); 73

Când componenta nu este gestionată de un gestionar de poziţionare (acest lucru se realizează printr-un apel setLayoutManager(null) pentru container), atunci ea va fi întotdeauna afişată cu dimensiunile şi poziţia care i-au fost atribuite în prealabil. Dacă nu i s-au asociat dimensiuni, implicit acestea vor fi 0, iar dacă nu a fost poziţionată, va fi aşezată în colţul din stânga-sus al containerului. Este esenţială deci înţelegerea modului în care lucrează gestionarii de poziţionare, pentru a nu avea surprize la momentul desenării containerului. De asemenea, trebuie ştiut că, implicit, panourilor reprezentând containere intermediare li se asociază managerul FlowLayout, iar panoului conţinut al unui container de bază i se asociază gestionarul BorderLayout. Se poate alege ca mai multe componente să fie grupate folosind containere intermediare, astfel având posibilitatea de a le gestiona împreună poziţionarea, separat de toate celelalte componente. Fiecare componentă grafică are asociate trei dimensiuni explicate în tabelul care urmează împreună cu metodele prin care acestea pot fi accesate: Dimensiuni Metode de acces preferredSize getPreferredSize() setPreferredSize() Explicaţii Dimensiunea preferată a unei componente. Este folosită de cei mai mulţi gestionari de poziţionare pentru a dimensiona implicit componentele. Dimensiunea preferată a unei componente este determinată de look--and-feel-ul componentei şi de fonturile pe care componenta le foloseşte. Folosită de gestionarii de poziţionare ca limită în micşorarea dimensiunilor componentelor. Folosită de gestionarii de poziţionare ca limită în maximizarea dimensiunilor componentelor.

minimumSize maximumSize

getMinimumSize() setMinimumSize() getMaximumSize() setMaximumSize()

Metodele de forma setXXXSize(), prezentate în tabelul precedent, primesc ca intrare o instanţă a clasei java.awt.Dimension. In exemplul următor, vom seta dimensiunea listei din exemplul precedent pentru a avea lăţimea de 200 pixeli şi înălţimea de 100 pixeli. Dimension dim = new Dimension(200,100); lista.setPreferredSize(dim); Pentru ca o componentă să fie desenată într-adevăr cu dimensiunile pe care le-am specificat în prealabil, trebuie să ne asigurăm că aceasta este administrată de un gestionar de poziţionare care respectă aceste setări. Spre exemplu, FlowLayout şi GridBagLayout respectă dimensiunile preferate ale componentelor. Nu acelaşi lucru se întâmplă cu BorderLayout şi GridLayout. Gestionarul BoxLayout este singurul gestionar care respectă dimensiunile maxime. 74

Dacă se doreşte redimensionarea unei componente care este deja vizibilă, ea trebuie redesenată după setarea noilor dimensiuni. Pentru a aduce componentele la dimensiunile lor preferate (engl. preferred size), vom apela metoda pack() pentru container înainte de a apela setvisible(). Pe lângă setarea dimensiunilor putem, de asemenea, modifica poziţia fiecărei componente în interiorul containerului. Când componenta nu este gestionată de un manager de poziţionare, acest lucru este uşor. In schimb, un manager de poziţionare poate neglija dimensiunile pe care le dăm componentei. Metoda setBounds() moştenită din JComponent poate fi folosită pentru a seta în acelaşi timp mărimea şi poziţionarea unei componente în interiorul containerului--părinte. Prezentăm în continuare cele două supraîncărcări ale metodei folosite în cazul exemplului anterior: lista.setBounds(200, 200, 400, 300) ; sau : Rectangle drept = new Rectangle(200, 200, 400, 300); lista.setBounds(drept); Pentru a obţine efectul scontat, va trebui ca după apelarea constructorului din superclasă să indicăm folosirea gestionarului pentru poziţii absolute, astfel: this.setLayout(null); De asemenea, toate componentele grafice Swing sunt construite conform specificaţiei JavaBeans, ceea ce înseamnă că sunt, de fapt, componente JavaBeans. Ce putem spune acum este că această compatibilitate dă posibilitatea construirii de medii vizuale pentru Java în care interfaţa grafică pentru aplicaţii se construieşte interactiv prin aşezarea componentelor grafice pe suprafaţa de lucru. Astfel, se pot testa efectiv mai multe posibilităţi de a proiecta interfaţa aplicaţiei până se ajunge la o formă definitiv acceptată. Pentru a putea folosi componentele Swing trebuie să importăm mai întâi pachetele corespunzătoare. In general, este de ajuns să includem următoarele pachete: • • • • javax.swing javax.swing.event java.awt java.awt.event 75 pentru componente Swing simple; pentru evenimentele generate de componentele Swing; pentru componentele din AWT;

pentru evenimente generale definite în AWT.

5.2.Fundamente Swing
Evenimente şi ascultători In Swing, interfaţa grafică (reprezentată de componentele grafice membre) este separată clar de implementare, care reprezintă codul ce se doreşte a fi executat în urma interacţiunii utilizatorului cu interfaţa. Din acest motiv, prin construcţie, Swing a fost conceput ca un sistem condus de evenimente. Evenimentele sunt generate (engl. fire) de fiecare dată când apăsam o tastă sau un buton al mouse-ului şi sunt tratate corespunzător prin cod scris de programator. Acest mod în care componentele aruncă evenimente şi felul în care acestea sunt tratate a rămas neschimbat de la platforma JDK 1.1 în care a fost implementat pentru prima oară. Sunt multe tipuri de evenimente pe care componentele Swing le pot genera. Fiecare eveniment este înfăşurat într-un obiect derivat din clasa java.util.EventObject prin intermediul căruia programatorul mânuieşte evenimentul, putând determina sursa sa (componenta care îl generează) şi, uneori, informaţii despre tipul evenimentului, starea sursei înainte şi după ce evenimentul a fost generat. Sursele evenimentelor sunt, în general, componente sau modele, dar există şi alte tipuri de obiecte care generează evenimente. In cazul evenimentelor derivate din clasa EventObject sursa se determină efectiv folosind metoda public Object getSource(). Informaţii despre tipul evenimentului se obţin printr-un apel al metodei publicStringtoString(). Evenimentele sunt grupate în două pachete: clasicul java.awt.event, care se refera la evenimente generale, respectiv java.swing.event, care se referă la evenimentele specifice componentelor grafice Swing. Pentru a trata evenimentul generat de o componentă, programatorul trebuie să asocieze acesteia un obiect ascultător (engl. listener) care conţine descrierea reacţiei aplicaţiei la apariţia evenimentului respectiv. Dacă un eveniment are tipul XXEvent, atunci ascultătorul este o implementare a interfeţei XXListener, care se găseşte, de asemenea, în unul dintre pachetele java.awt.event sau java.swing.event. Desenarea componentelor grafice Tot ceea ce este vizualizat pe ecran la un moment dat, în urma execuţiei unei aplicaţii având interfaţă grafică, rezultă în urma unui proces de desenare. Componentele sunt desenate. 76

Procesul de desenare începe cu containerele de bază şi se continuă cu conţinutul. Componentele Swing se redesenează singure atunci când este nevoie, spre exemplu, atunci când schimbăm dimensiunile ferestrei sau când fereastra revine în prim-plan după ce a fost acoperită de o altă fereastră. Sau când apelăm pentru o etichetă o metodă de genul setText(), spre exemplu, eticheta se va redesena singură (conţinând noul text) şi se va şi redimensiona pentru a-l cuprinde. Utilizatorul nu trebuie să aibă în vedere desenarea doar în cazul în care doreşte să creeze propriile lui componente sau să depaneze procesul de desenare. In Swing, pentru ca o componentă să aibă acces la desenarea sa, este necesar să suprascrie metoda paintComponent(), spre deosebire de AWT, unde trebuia supra-scrisă paint(). In interiorul acestei metode avem acces la obiectul de tip Graphics pe care componenta îl conţine, cunoscut şi sub numele de contextul grafic al obiectului (engl. graphic context). Clasa Graphics conţine multe metode care permit desenarea figurilor geometrice sau scrierea de text cu diferite fonturi, dimensiuni şi culori. Clasa Graphics foloseşte ceea ce se numeşte zona de lucru (engl. clippingarea). In interiorul unei metode paint(), această zonă reprezintă regiunea din vizualizarea componentei care va fi redesenată. Mai poartă numele de regiunea murdărită (engl. dirtied) a componentei şi numai această zonă va fi reactualizată prin redesenarea componentei. Putem determina dimensiunile acestei regiuni folosind metoda getBounds(), pe care o pune la dispoziţie clasa Graphics. Suprafaţa de desenare se poate micşora din motive de eficienţă, spre exemplu, nefiind necesară desenarea unei anumite regiuni la un moment dat. In procesul de desenare, Swing foloseşte o tehnică care se numeşte buffer dublu (engl, double-buffering), care reprezintă desenarea într-o imagine, şi nu desenarea direct într-o componentă vizibilă pe ecran. La finalul procesului de desenare imaginea este vizualizată pe ecran. Spre deosebire de Swing, în AWT dezvoltatorii erau cei responsabili pentru implementarea acestui mecanism pentru a reduce flash-urile. Pentru a seta/deseta acest mecanism pentru o componentă Swing se foloseşte metoda public void setDoubleBuffered (boolean aFlag) din clasa JComponent. Dacă am setat buffer-ul dublu pentru o anumită componentă, toate componentele conţinute se vor desena folosind acest mecanism. Clasificarea componentelor Swing

77

Componentele swing pot fii imparţite in trei categorii, si anume: containere de baza, containere intermediare si componente atomice. Diferenţele dintre acestea sunt prezentate in tabelul următor:
Tip componenta Containere de baza Explicatii Orice aplicaţie care deţine o interfaţă grafică are cel puţin un astfel de container. Componentele (care nu pot fi tot containere de bază) se vor adăuga acestui container. Reprezintă locul în care toate celelalte Containere intermediare componente se vor desena. Scopul lor este acela de a grupa mai multe componente şi de a simplifica poziţio-narea, dimensiunile şi modul în care com-ponentele conţinute vor reacţiona la modificarea dimensiunilor ferestrei de bază. Pentru aceasta li se ataşează Containere atomice gestionari de poziţionare (engl. layout manageri). Nu au, precum celelalte tipuri de componente, rolul de a ţine alte componente, ci sunt suficiente pentru a prezenta informaţia pe care o deţin utilizatorului sau pentru a primi informaţii de la utilizatorii interfeţei grafice. Mai pe scurt, îşi sunt lor suficiente pentru a interacţiona cu utilizatorul. JLabel, JButton JList, JComboBox, JTextField, JtextArea, JTable, JTree, JMenu, JPopup, JMenuItem, JToolBar, JOptionPane, JFileChooser, JColorChooser, JSlider, JScrollBar, JProgressBar, JDesktopBar, JInternalFrame JPanel, JScrollPane JSplitPane Componente JFrame, JWindow, JDialog, JApplet, JInternalFrame

Containere de bază Toate containerele de bază implementează interfaţa RootPaneContainer şi din acest motiv au aceeaşi organizare internă. Diferenţa dintre aceste containere şi celelalte componente S w i n g este faptul ca ele moştenesc direct clasele corespondente lor din AWT, aşa cum se poate observa în figura care urmează. Toate celelalte componente moştenesc clasa JComponent, şi nu componentele corespondente din AWT. Din acest motiv, ele sunt singurele componente „grele" din Swing (engl. heavyweight), fiind indirect dependente de componentele corespondente (engl. peer) native ale sistemului de operare peste care este instalată platforma Java. Totuşi, Swing 78

oferă independenţa faţă de sistemul de operare de pe maşina gazdă (în sensul look-andfeel-ului componentelor care rămâne identic pentru toate sistemele şi maşinile) tocmai prin modul în care aceste containere sunt construite, conţinutul lor fiind gestionat de o componentă panou „uşoară", şi anume o instanţă JRootPane,

JFrame Containerul cel mai des folosit pentru o aplicaţie bazată pe Swing este JFrame. Modul în care această componentă este construită este mult mai complicat decât cel al componentei corespondente din AWT, şi anume Frame. Orice fereastră JFrame conţine un câmp protected cu numele rootPane, care este o instanţă a clasei JRootPane, servind drept container pentru alte câteva componente panou. Nu putem adăuga componente direct unei ferestre JFrame, ci unuia dintre panourile conţinute în rootPane (nu lui rootPane, care este doar un panou intermediar). Pentru a adăuga o componentă unei ferestre JFrame trebuie, de fapt, să ataşăm acea componentă panoului contentPane şi acest lucru se realizează prin apeluri de genul: fereastraMea.getContentPane().add(componentaMea). De asemenea, putem recurge la un apel; JPanel conţinut = (JPanel) getContent Pane(), obţinând astfel panoul conţinut, căruia putem săi adăugăm componente folosind apeluri de tipul add().

Pentru a seta gestionarul de poziţionare pentru o fereastră vom folosi un apel de forma: fereastraMea.getContentPane().setLayout(new FlowLayout().Dacă vom încerca să utilizăm metode de t i p add () sau setLayout () direct pentru fereastra JFrame vom obţine eroare. De remarcat metoda getContentPane(), pe care clasa JFrame o pune la dispoziţie pentru obţinerea unei referinţe la atributul contentPane asociat ferestrei. Componenta glassPane este implicit un panou JPanel neopac care stă deasupra tuturor componentelor din JRootPane, acţionând ca un ecran de protecţie pentru fereastra. Acest lucru permite desenarea deasupra tuturor componentelor din fereastra curentă, precum şi interceptarea sau întreruperea evenimentelor generate de mouse. Pentru a schimba glassPane din JPanel în oricare altă componentă folosim metoda public void setGlassPane (Component glassPane) pe care clasa JFrame o pune la dispoziţie. O referinţă spre componenta glassPane curentă asociată unei ferestre se obţine prin metoda public Component getGlassPane() t o t din clasa JFrame. Implicit, glassPane care acoperă layeredPane nu este vizibilă, dar poate fi prin apelul getGlassPane().seeVisible (true). LayeredPane este una dintre cele mai puternice şi mai robuste componente din pachetul Swing. Reprezintă un container care oferă o a treia dimensiune pentru a poziţiona componente, şi 79

anume adâncimea (engl. Z-order). Este un container având un număr nelimitat de straturi (engl. layers), pe care componentele pot sta. Pe un acelaşi strat putem aşeza în acelaşi timp un număr nelimitat de componente. Atunci când adăugăm o componentă unui obiect de tip LayeredPane, trebuie să specificăm şi adâncimea sub forma unui întreg care reprezintă numărul stratului. Cu cât numărul este mai mare, cu atât adâncimea este mai mică. Apare în acest fel fenomenul de suprapunere a componentelor conţinute, acest lucru putând fi foarte util. JWindow Componenta JWindow este asemănătoare cu JFrame, cu excepţia faptului că nu are bară de titlu, nu i se pot modifica dimensiunile, nu se poate minimiza, maximiza şi nu poate fi închisă. JWindow poate fi folosită pentru a vizualiza un mesaj temporar sau siglele de la începutul utilizării aplicaţiei. Deoarece implementează interfaţa RootPaneContainer, necesită acelaşi comportament din partea dezvoltatorului pentru a-i accesa conţinutul. JDialog Această clasă este folosită pentru a crea o fereastră de dialog ale cărei structură şi comportament sunt identice cu JFrame. Un dialog permite realizarea interacţiunii utilizatorilor cu aplicaţia în timpul folosirii ei, permiţând introducerea şi obţinerea de informaţii. Prin diversitatea de constructori oferiţi putem crea o fereastră JDialog modală sau nemodală, dependentă sau nu de un alt container. Dacă este modală, nu se permite altor ferestre să fie active în acelaşi timp cu ea. Dacă este dependentă de un părinte, dialogul se va activa doar în strânsă legătură cu el, altfel aplicaţia poate să aibă drept interfaţă grafică un simplu dialog şi nimic altceva. Containere intermediare Containerele intermediare le vom numi panouri (engl. panel, pane) şi sunt următoarele: JPanel, JScrollPane, JSplitPane, JTabbedPane. Panourile reprezintă modalitatea standard de a aduna mai multe componente „uşoare" la un loc şi de a le gestiona poziţionarea şi dimensiunile folosind managerii de poziţionare. Implicit, gestionarul de poziţionare pentru un panou este FlowLayout. De aceea, atunci când adăugăm componente într-un panou, căruia nu i-am setat alt gestionar de poziţionare, acestea se vor poziţiona pe aceeaşi linie, una după alta, cu dimensiunile lor preferate (engl. preferred size). Atunci când o componentă nu mai încape pe rândul curent din cauza dimensiunilor ei, se aşează pe linia următoare. Implicit, panourile nu desenează nimic 80

altceva decât culoarea fundalului (engl. background) lor. Permit adăugarea de chenare şi li se poate personaliza desenarea JPanel Clasa JPanel reprezintă containerul intermediar de bază pentru orice interfaţă grafică, folosit de cele mai multe ori pentru a organiza un grup de componente ale unui alt container care le conţine. Se ştie că şi conţinutul unei ferestre este redat tot într-un panou implicit JPanel, numit contentPane, care, atenţie, este gestionat implicit de gestionarul BorderLayout. Prezentăm în continuare constructorii clasei JPanel:
Constructor

JPanel() JPanel(LayoutManager lm)

Explicaţie Creează un panou. Creează un panou având gestionarul de poziţionare lm.

Prezentăm metodele clasei JPanel care permit adăugarea, accesul şi ştergerea componentelor dintr-un container, adăugarea de gestionari de poziţionare, setarea chenarelor, remarcând că toate sunt moşteniri din superclasele derivate.
Metoda

void add(Component) void add(Component, int) int getComponentCount() Component getComponent(int i) Component getComponentAt(int x,int y) Component getComponentAt(Point p) Component[] getComponents() void remove(Component c) void remove(int i) void removeAll() void setLayout(LayoutManager lm) LayoutManager getLayout() public void setBorder(Border border)

Explicaţie Adaugă o componentă panoului. Dacă parametrul întreg este prezent, el indica indicele cu care componenta se adaugă în container. Returnează numărul de componente din panou. Permit obţinerea componentei cu un anumit index, având coordonatele x, y sau aflându-se în punctul p. Returnează intr-un vector toate componentele containerului. Șterge componenta c, pe cea cu indicele i sau pe toate Se setează, respectiv se obţine o referinţă la managerul de poziţionare. Setează bordel-ul pentru panou.

JScrollPane La o primă vedere această componentă pare extrem de simplă. Scopul ei este acela de a da posibilitatea derulării (engl. scrolt) celorlalte componente în cazul în care ele nu încap într-o 81

zonă cu dimensiuni fixe. De notat că nu permite derularea componentelor „grele" . De asemenea, poziţionarea pentru această componentă este gestionată de un manager special numit ScrollPaneLayout şi nu se pot seta gestionarii de poziţionare obişnuiţi. JTabbedPane JTabbedPane reprezintă o stivă de componente (de obicei, panouri JPanel sau containere, în general) aşezate pe mai multe straturi suprapuse, unul dintre ele putând fi selectat la un moment dat, determinând componenta conţinută să devină vizibilă. Straturile au câte o prelungire (engl. tab) care are proprietăţile unei etichete, putând conţine o pictogramă, culoare de fundal sau tooltip. Pentru a adăuga componente unui JTabbedPane putem folosi diverse supraîncărcări ale metodelor add(),addTab() sau insertTab(), pe care clasa JTabbedPane le pune la dispoziţie. Pentru fiecare componentă adăugată unui panou JTabbedPane se va crea un strat unde aceasta va fi aşezată; stratul va avea o prelungire cu forma unei etichete prin intermediul căreia utilizatorii vor selecta stratul pe care vor s a i l vizualizeze. Fiecare strat are asociat un indice, numerotarea implicită pornind de la stânga spre dreapta, începând cu 0 . Dacă numărul de straturi este mai mare decât 0, va exista întotdeauna un indice care va fi selectat şi care corespunde stratului vizibil. Implicit, este selectat stratul cu indicele 0 , Indicele curent se obţine folosind metoda care are prototipul public int getSelectedlndex (). Componente atomice simple JLabel Etichetele permit afişarea de informaţii care nu pot fi selectate sau suprascrise. De exemplu, se pot afişa text sau imagini, separat sau împreună, fără a se aştepta acţiuni din partea utilizatorilor, deoarece o etichetă nu poate deţine comunicarea cu tastatura (engl. focus). Pentru interacţiune se vor folosi butoane, etichetele putând, eventual, fi folosite pentru a descrie butoane sau alte componente. Pentru a adăuga şi poziţiona conţinutul unei etichete se poate folosi unul dintre constructorii puşi la dispoziţie sau metoda setText() pentru a adăuga text, respectiv setIcon() pentru a adăuga imagini. Alinierea conţinutului unei etichete se poate seta cu una dintre metodele: setHorizontalAlignment(int aliniament) sau setVerticalAlignment(int aliniament), unde alinierea este una dintre constantele definite în interfaţa SwingConstants. Implicit, textul este indentat la dreapta, pe când pictogramele sunt centrate. Vertical, conţinutul este aliniat 82

implicit centrat, indiferent dacă este text sau imagine. Pentru o etichetă se mai pot seta culoarea de fundal, culoarea textului, fontul etc, folosind metodele pe care clasa J L a b e l le pune la dispoziţie. Butoane Toate componentele reprezentând butoane în Swing extind clasa AbstractButton. De remarcat că şi clasele JMenuItem, JCheckBoxMenuItem şi JRadioButtonMenuItem, care desemnează opţiuni într-un meniu, extind AbstractButton. Prezentăm în tabelul care urmează o listă a componentelor grafice având rol de butoane, cu un exemplu de reprezentare grafică, urmat de explicaţiile corespunzătoare: Buton JButton Vizualizare Explicaţie Un buton simplu a cărui apăsare determină aruncarea unui eveniment care trebuie tratat de programator. Prin apăsare, butonul îşi schimbă şi vizualizarea, iar după eliberarea butonului mouse-ului se va reveni la forma iniţiala. Un buton care permite comutarea între două stări. Permite personalizări ale butoanelor JCheckBox şi JRadioButton, fiind şi superclasă pentru acestea. Un buton a cărui stare poate fi setată între bifat sau nebifat. Un buton radio, în general, formează împreună cu alte butoane radio un grup dintre care numai unul poate fi apăsat la un moment dat.

JToggleBu tton JCheckBox JRadioBut ton

Stările în care se poate găsi un buton la un moment dat sunt date de următoarele proprietăţi: Stare Selectat (engl. selected) Apăsat (engl. pressed) Derulant (engl, rollover) Armat (engl. armed) Explicatii Arată dacă s-a schimbat starea butonului prin apăsarea şi apoi eliberarea butonului mouse-ului (această proprietate are valoare doar în cazul JToggleButton ce are două stări bifat/nebifat). Are valoarea true atunci când butonul mouse-ului a fost eliberat, după ce iniţial a fost apăsat. Are valoarea true atunci când se tratează cazul în care cursorul mouseului se află deasupra suprafeţei butonului. Un buton se află în această stare dacă este apăsat cu mouse-ul fără a ridica degetul de pe buton; este folosită pentru a opri aruncarea evenimentului care generează tratarea, atunci când am apăsat un buton şi 83

Activat (engl. enabled)

mai apoi îl eliberăm având cursorul mouse-ului afara suprafeţei butonului (renunţăm să mai apăsam butonul). Are valoarea true când butonul poate recepta acţiunile care se fac asupra lui cu mouse-ul sau tastatura (deţine focusul) şi în acest caz celelalte proprietăţi nu pot să-şi schimbe starea când e false.

Dacă apăsam cu mouse-ul un buton simplu, JButton, acesta se va „arma", pe când pentru un JToggleButton, acesta va deveni selectat. Butoanele folosesc un model pentru a gestiona stările în care se pot afla la un moment dat. Acesta poartă numele ButtonModel şi reprezintă baza pentru realizarea de modele pentru butoane. Putem avea acces la acest model folosind metodele getModel (), respectiv setModel(), prima pentru a obţine modelul, iar a doua pentru a seta un nou model pentru butonul curent. Dacă nu precizăm nici un model, implicit se va asocia DefaultButtonModel, care reprezintă implementarea implicită ce ne este pusă la dispoziţie pentru modelul ButtonModel. În general, în practică, nu este nevoie să creăm propriul model pentru butoane, fiind de ajuns să folosim unul dintre constructorii puşi la dispoziţie, JButton U n buton poate prezenta atât text, cât şi imagini. O imagine poate fi ataşată unui buton folosind constructorul care are ca parametru o instanţă a clasei Icon sau, după desenare, folosind metoda setIcon(Icon imagine). Putem adăuga pictograme care să apară în diferite stări ale butonului, când este selectat, apăsat, dezactivat etc. Unui buton i se poate asocia drept accelerator o literă din textul pe care îl prezintă drept conţinut (aceasta va deveni subliniată) folosind un apel de genul setMnemonic ('B'). In Windows, apăsarea tastei A L T şi a tastei reprezentând litera respectivă determină declanşarea acţiunii. Tratarea evenimentelor generate de butoane se face în funcţie de tipul de buton. In general, se adaugă ascultători ActionListener care tratează evenimentul aruncat de apăsarea butonului. In cazul JCheckBox şi JRadioButton se foloseşte un ascultător ItemListener pentru a testa dacă butonul este sau nu selectat. Un singur buton al interfeţei grafice poate deţine legătura cu tastatura la un moment dat, ceea ce înseamnă că apăsarea tastei spaţiu (engl. spacebar key) în acel moment determină declanşarea acţiunii asociate butonului. Pentru a selecta butonul implicit care deţine focusul la startarea aplicaţiei, folosim un apel fereastraMea. getRootPane().setDefaultButton(buton). Un buton poate fi dezactivat (nu va mai răspunde la acţiunile utilizatorilor efectuate asupra lui) folosind metoda setEnabled(boolean stare). 84

JToggleButton, JCheckButton, JRadioButton Componentele JCheckButton, JRadioButton şi JToggleButton au aceeaşi funcţionalitate, permiţând simularea unui comutator (engl. switch) cu două stări. Singura diferenţă dintre toate aceste componente o reprezintă instanţele UIDelegate care le dau vizualizarea şi care sunt diferiţi. De remarcat faptul că JCheckButton şi JRadioButton moştenesc clasa JToggleButton, care oferă pentru acestea mecanismul de comutare între cele două stări posibile. Putem verifica dacă un buton este selectat folosind metoda isSelected() şi îl putem selecta efectiv utilizând metoda setSelected(boolean stare). Folosind clasa ButtonGroup putem grupa mai multe butoane împreună pentru a garanta că numai unul poate fi selectat la un moment dat. Gruparea se poate face doar pentru butoanele care moştenesc JToggleButton, deoarece numai acestea sunt selectabile. Chenare Rolul chenarelor (engl. borders) este important în realizarea unei interfeţe grafice prietenoase. Prin intermediul lor putem crea butoane care să se distingă de context, umbre pentru zonele de text, putem separa între ele componentele. Chenarele nu sunt componente (nu moştenesc JComponent), astfel î n c â t nu le putem asocia ascultători, tooltips etc. Clasa din care sunt derivate toate chenarele, şi anume AbstractBorder, este derivată direct din clasa Object, la fel ca toate clasele d i n Java. Clasele reprezentând diverse chenare se află localizate în pachetul javax.borders care trebuie importat pentru a le putea folosi. Swing pune la dispoziţia utilizatorilor o serie de chenare standard care pot fi folosite în obţinerea de chenare compuse, personalizate. Lista lor o prezentăm în continuare: Chenar CompoundBorder EmptyBorder EtchedBorder LineBorder MatteBorder SoftBevelBorder TitledBorder Explicatia O combinaţie de două chenare: una interioară şi una exterioară. Reprezintă metoda prin care se pot compune chenare. Un chenar transparent folosit doar pentru a defini spaţiul liber în jurul componentelor. Un chenar având forma unei linii care apare în relief. Un chenar plan cu o grosime şi culoare specificate. Un chenar constând dintr-o culoare sau o mică imagine. Un chenar 3D ridicat sau coborât, cu colţurile rotunjite. Un chenar care afişează un titlu într-o anumită poziţie. Putem specifica fontul titlului, culoarea, indentarea şi poziţionarea folosind metodele şi constantele clasei TitleBorder. 85

Pentru a seta chenarul unei componente se utilizează metoda setBorder() pe care acestea o moştenesc din clasa JComponent. Mai există, de asemenea, o clasă care poartă denumirea de BorderFactory, care se află în pachetul javax.swing, ce conţine metode statice - pot fi folosite pentru a construi chenare de diferite tipuri. JList Această componentă permite utilizatorilor să aleagă un element dintr-o listă de obiecte. Conţinutul unei liste este gestionat printr-un model care este o instanţă a clasei ListModel. Putem preciza că JList oferă acces la conţinutul listei doar prin intermediul modelului de date asociat. Constructorii acestei componente permit crearea de liste direct dintr-un tablou având drept elemente instanţe de clase derivate din clasa Object sau dintr-un vector Vector (care, la rândul lui, este o colecţie de elemente Object). Ceea ce va fi afişat ca text în listă, ţinând cont că elementele listei sunt instanţe Object, va fi şirul rezultat din apelul toString() al obiectelor (numai în cazul instanţelor clasei Icon se va face tipărirea lor ca pictograme în etichete). In cazul în care nu asociem un model de date explicit, conţinutul este gestionat tot prin intermediul unui model ListModel implicit, şi anume o instanţă a DefaultListModel, care este alocată componentei. Clasa DefaultListModel este o implementare implicită a modelului ListModel şi ţine în interior lista sub forma unui vector de obiecte Object. Mai există o implementare abstractă pentru ListModel, şi anume AbstractListModel, care permite programatorului să aleagă structura de date in care să păstreze lista. JComboBox Componenta JComboBox combină un buton (care se transformă într-un câmp text când componenta este editabilă) cu o listă expandabilă la cerere din care utilizatorul poate să selecteze o singură opţiune la un moment dat. Deoarece componenta JComboBox are aceeaşi funcţionalitate ca JList, este dificilă alegerea între aceste două posibilităţi. Se recomandă folosirea componentei JComboBox în defavoarea JList, în cazul în care se doreşte ca utilizatorul să poată să aleagă o singură opţiune pe care să o vadă explicit mai apoi. Când componenta este setată să fie editabilă, atunci va conţine un câmp text (şi nu un buton) în care utilizatorul poate introduce date de intrare. Intern, această componentă este construită dintr-un buton şi un meniu JPopupMenu, care conţine o listă JList (reprezentând opţiunile posibile) aşezată mai întâi într-un panou JScrollPane pentru a se putea derula. 86

Această componentă permite folosirea mai multor constructori asemănători componentei JList. Se poate construi un JComboBox folosind un model dat explicit, care este o instanţă a clasei ComboBoxModel şi, în acest caz, vom avea acces maxim asupra proprietăţilor şi comportamentului componentei. Putem să creăm o componentă JComboBox direct dintr-un tablou de obiecte Object sau dintr-un vector Vector. Mai putem crea un JComboBox vid, căruia îi putem asocia mai apoi un model de date. Trebuie să precizăm că avem la dispoziţie clasa DefaultComboBoxModel, care este implementarea implicită pentru ComboBoxModel şi pe care o putem folosi drept model efectiv pentru componentele noastre. Mai există un model, şi anume interfaţa MutableComboBoxModel, ce face posibile operaţiile de adăugare, ştergere şi modificare în mod dinamic a conţinutului componentei JComboBox care o foloseşte ca model de date. JTable JTable este componenta grafică care permite operarea cu tabele. Clasa JTable din pachetul javax.swing extinde direct clasa JComponent, implementând interfeţele TableModelListener, TableColumnModelListener, ListSelectonListener, CellEditorListener şi Scrollable. JTable are asociate, de asemenea, trei modele: TabLeModel, TableColumnModel şi ListSelectionModel, fiecare gestionând o anumită caracteristică a acestei componente. De asemenea, datorita com-plexităţii acestei componente, JTable are un întreg pachet dedicat, şi anume javax.swing.table. Componenta JTable este construită pe acelaşi principiu clasic în Swing, numit modeldelegat (engl. model-delegate), care reprezintă, de fapt, o despărţire a datelor de modul lor de vizualizare. Datele tabelei vor fi întotdeauna ţinute într-o matrice, într-o listă de vectori, sau o listă de liste, de fapt, orice structură de date tabelară. Reprezentarea grafică a datelor (engl. look) este încapsulata împreună cu modul în care componenta reacţionează la acţiunile utilizatorilor (engl. feel) într-un obiect, care poartă denumirea delegate, asociat fiecărei componente grafice. Componenta joacă astfel rolul unui mediator între vizualizare şi datele care reprezintă conţinutul ce se vrea vizualizat. Pentru JTable obiectul delegate implicit are numele TableUI, se găseşte în pachetul javax.swing.plaf şi poate fi schimbat prin adăugarea unui plug-in nou pentru schimbarea vizualizării şi comportării la acţiunile utilizatorilor. Această clasă dă, cu alte cuvinte, pentru componenta JTable vizualizarea şi comportamentul (engl. look-and-feel). Datele ce se doresc vizualizate sunt la rândul lor înfăşurate într-un model care prin sistemul de ascultători actualizează automat vizualizarea în urma modificărilor făcute în structura de date. Spre 87

exemplu, atunci când vrem să ştergem o înregistrare dintr-o tabelă, o ştergem din structura care ţine datele şi atenţionăm componenta JTable care o înfăşoară să se reactualizeze.

6. Realizarea interfeței grafice BYBLIOTON pentru gestionarea unei biblioteci
“Open source" desemnează dezvoltarea de programe software de către o comunitate, de către o companie sau de către o persoană şi oferirea lor spre folosire sau îmbunătăţire sub licenţă GPL.(General Public License). Licenta open-source este caracterizata de libertatea acordată utilizatorilor săi de a-l utiliza, copia, redistribui, studia, modifica şi îmbunătăţi. Mai exact, este vorba de următoarele patru forme de libertate pentru utilizatorii săi: Libertatea de a utiliza programul, în orice scop Libertatea de a studia modul de funcţionare a programului, şi de a-l adapta nevoilor proprii . "Open source" asigură accesul la tot codul-sursă. Libertatea de a redistribui copii, în scopul ajutorării aproapelui tău . 88

-

Libertatea de a îmbunătăţi programul, şi de a pune îmbunătăţirile la dispoziţia publicului, în folosul întregii societăţi . Necesită accesul la codul-sursă.

Un program (o aplicaţie) este open-source dacă întruneşte toate aceste libertăţi. Astfel, oricine oriunde ar trebui să fie liber să redistribuie copii, modificate sau nu, în mod gratuit sau contra unei sume pentru costurile de desfacere. Aceste libertăţi înseamnă (printre altele) că nu este necesar a cere sau a plăti pentru a primi permisiune în acest scop. Pentru realizarea programului nostru avem nevoie de un sisetm de gestiune al bazelor de date MySQL si de un mediu de dezvoltare Java NetBeans. NetBeans este un proiect open-source IDE (Integrated Development Environment ) – mediu integrat de dezvoltare. Contine toate uneltele de care avem nevoie pentru a crea ecrane profesionale, situri web, aplicatii pe telefoane mobile cu ajutorul limbajelor de programare Java, C/C++ si a limbajelor dinamice PHP, JavaScript, Groovy si Ruby. NetBeans este usor de instalat si utilizat, poate rula pe mai multe platforme Windows, Linux, Mac OS si Solaris. NetBeans IDE 6.5 oferă caracteristici noi si îmbunătățiri in lucrul cu PHP, JavaScript si funcții de editare pentru Ajax , suport îmbunătățit pentru utilizarea web framework si Java Persistence API si ofera suport pentru integrarea MySQL si GlassFish v3. MySQL este un sistem de gestiune a bazelor de date relaţional, produs de compania suedeză MySQL AB şi distribuit sub Licenţa Publică Generală GNU. Este cel mai popular SGBD open-source la ora actuală, fiind o componentă cheie a stivei LAMP (Linux, Apache, MySQL, PHP). Deşi este folosit foarte des împreună cu limbajul de programare PHP, cu MySQL se pot construi aplicaţii în orice limbaj major. Există multe scheme API disponibile pentru MySQL ce permit scrierea aplicaţiilor în numeroase limbaje de programare pentru accesarea bazelor de date MySQL, cum are fi: C, C++, C#, Borland Delphi, Java, Perl, PHP, Python, FreeBasic, etc., fiecare dintre acestea folosind un tip spefic API. O interfaţă de tip ODBC denumită MyODBC permite altor limbaje de programare ce folosesc această interfaţă, să interacţioneze cu bazele de date MySQL cum ar fi ASP sau Visual Basic. În sprijinul acestor limbaje de programare, unele companii produc componente de tip COM/COM+ sau .NET (pentru Windows) prin intermediul cărora respectivele limbaje să poată folosi acest SGBD mult mai uşor decât prin intermediul sistemului ODBC. Aceste componente pot fi gratuite (ca de exemplu MyVBQL) sau comerciale.

89

Licenţa GNU GPL nu permite încorporarea MySQL în softuri comerciale; cei care doresc să facă acest lucru pot achiziţiona, contra cost, o licenţă comercială de la compania producătoare, MySQL AB. MySQL este componentă integrată a platformelor LAMP sau WAMP (Linux/WindowsApache-MySQL-PHP/Perl/Python). Popularitatea sa ca aplicaţie web este strâns legată de cea a PHP-ului care este adesea combinat cu MySQL şi denumit Duo-ul Dinamic. În multe cărţi de specialitate este precizat faptul ca MySQL este mult mai uşor de învățat şi folosit decât multe din aplicaţiile de gestiune a bazelor de date, ca exemplu comanda de ieşire fiind una simplă şi evidentă: „exit” sau „quit”. Pentru a administra bazele de date MySQL se poate folosi modul linie de comandă sau, prin descărcare de pe internet, o interfaţă grafică: MySQL Community Server şi Gui-Tools, de la adresa http://dev.mysql.com/downloads/mysql/5.0.html , respectiv http://dev.mysql.com/downloads/gui-tools/5.0.html . In cazul proiectarii unei baze de date MySQL mai ofera un produs sub licenta GPL, MySQL Workbench, este o noua generatie de design de baze de date care poate sa proiecteze in mod eficient, sa gestioneze si sa documenteze o baza de date o baza de date relaționala. Se poate downloada de la adresa http://dev.mysql.com/downloads/workbench/5.1.html.

Instalarea serverului MySQL. Se lansează in execuție programul MySQL Community si se executa următorii pași : Next – Typical, Next – Install – Next – Next – Finish. Se lansează automat in execuție MySQL Server Instance Configuration Wizard : Next – Standard configurationn, Next – Next – Se introduce parola si se confirma, Next – Execute – Finish. Prin pașii anteriori am instalat baza de date si am configurat-o. Acum se poate lucra cu baza de date direct din NetBeans. Daca suntem obișnuiți sa lucram cu baza de date in GUI Toolos – utilitarul grafic de la MySQL – se poate instala si acesta. Pentru a verifica baza de date nou creata se instaleaza MySQL Workbench, care are o funcție de construcție a diagramei entitate – relație, afișează tabelele , atributele si legăturile intre

90

tabele, in funcție de codul scris al bazei de date . Construcția unei baze de date este mult mai facila prin suportul grafic pe care îl oferă.

6.1.Crearea bazei de date
Cu ajutorul mediului de dezvoltare NetBeans putem construi o baza de date. In fereastra Services, găsim serverul local MySQL. Pentru a putea crea o baza de date in MySQL, trebuie sa ne conectam la server: click dreapta pe MySQL Server at localhost:3309[root]- Connect. După conectare creăm baza de date : click dreapta pe MySQL Server at localhost:3309[root]-

-Create Database … - in fereastra de dialog introducem numele bazei de date „Biblioteca” si confirmam. Astfel am creat baza de date Biblioteca.

In fereastra Services se găsește baza noastră de date nou creata . Se observa adresa bazei de date si directoarele ce le conține. In directorul Tables se introduc tabelele si atributele, cheile primare, cheile străine, indexurile.

91

Pentru a popula baza de date cu tabele avem doua posibilităţi:
a) Lucru in modul vizual click dreapta pe Tables – Create Table… - In fereastra care ne

apare putem denumii tabelul , putem adăuga atribute, se poate seta proprietățile fiecărui atribut (cheia primara, sa fie indexat sau nu, NULL sau NOT NULL, sa fie unica, denumirea atributului, tipul de data , dimensiona, comentarii, valoare implicita si constrângeri). După ce am adăugat in tabel toate atributele si le-am definit prin butonul de confirmare „OK” se creează tabelul nostru. Ca sa verificam compunerea tabelului in fereastra services in directorul Tables, se observa tabelul obținut si atributele adăugate, cheia primara , atributele indexate.

92

b) Al doilea mod de lucru este modul de lucru in linie de comanda ; click dreapta pe

directorul Tables – Execut Command… - in fereastra care apare putem introduce comenzile SQL de la tastatura si putem crea astfel tabelul , defini atributele, cheile primare, constrângerile. La lansarea in execuție a comenzilor apăsam iconul „Run SQL” sau combinația de taste Ctrl+Shift+E.

La lansarea in execuție a unei comenzi, in fereastra output o sa apară comentarii legate de rularea comenzii respective, timpul de execuție, daca s-a terminat cu succes sau are erori comanda respectiva. Daca găsește erori la compilare o sa anunțe si linia si coloana unde au apărut erorile respective.

93

In acest fel a fost creata baza de date Biblioteca, care o sa stocheze si o sa gestioneze informații legate despre cărţi,autori, edituri , cititori, cărţi împrumutate. Conectarea la o baza de date Procesul de conectare la o bază de date implica două operații: - încărcarea în memorie a unui driver corespunzător - realizarea unei conexiuni propriu-zise O conexiune (sesiune) la o bază de date reprezintă un context prin care sunt trimise secvenţe SQL şi primite rezultate. Intr-o aplicaţie pot exista mai multe conexiuni simultan la baze de date diferite sau la aceeasi baza. Clasele si interfețele responsabile cu realizarea unei conexiuni sunt: - clasa DriverManager, ce se ocupă cu înregistrarea driverelor ce vor fi folosite în aplicație - interfața Driver, pe care trebuie să o implementeze orice clasa ce descrie un driver clasa DriverPropertyInfo - interfața Connection, descrie obiectele ce modelează o conexiune propriu-zisă cu baza de date Incarnarea în memorie a unui driver Primul lucru pe care trebuie să-l facă o aplicaţie în procesul de conectare la o baza de date este să încarce în memorie clasa ce implementează driver-ul necesar comunicării cu respectiva baza de date. Acest lucru poate fi realizat prin mai multe modalităţi: 1. DriverManager.registerDriver(new sun.jdbc.odbc.JdbcOdbcDriver()); 2. Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 3. System.setProperty("jdbc.drivers", "sun.jdbc.odbc.JdbcOdbcDriver"); 4. java -Djdbc.drivers=sun.jdbc.odbc.JdbcOdbcDriver

94

Specificarea unei baze de date Odată ce un driver JDBC a fost încarcat în memorie, acesta poate fi folosit la stabilirea unei conexiuni cu o bază de date. Având în vedere faptul că pot exista mai multe drivere înregistrate în memorie, trebuie să avem posibilitea de a specifica pe lângă identificatorul bazei de date si driverul ce trebuie folosit. Aceasta se realizează prin intermediul unei adrese specifice, numită JDBC URL, ce are urmatorul format: jdbc:sub-protocol:identificator_baza_de_date Câmpul sub-protocol denumeşte tipul de driver ce trebuie folosit pentru realizarea conexiunii si poate fi odbc, oracle, sybase, db2 şi aşa mai departe. Identificatorul bazei de date este un indicator specific fiecărui driver care specifică baza de date cu care aplicaţia doreşte să interactioneze. In functie de tipul driver-ului acest identificator poate include numele unei maşini gazdă, un număr de port, numele unui fişier sau al unui director, etc. Realizarea unei conexiuni Metoda folosită pentru realizarea unei conexiuni este getConnection din clasa DriverManager si poate avea mai multe forme: Connection c = DriverManager.getConnection(url); Connection c = DriverManager.getConnection(url, username, password); Connection c = DriverManager.getConnection(url, dbproperies); O conexiune va fi folosită pentru: - crearea de secvenţe SQL ce vor fi folosite pentru interogarea sau actualizarea bazei - aflarea unor informaţii legate de baza de date (meta-date) Clasa Connection asigură suport pentru controlul tranzacţiilor din memorie către baza de date prin metodele commit, rollback, setAutoCommit.

6.2.Realizarea interfeței grafice
Pentru a realiza interfața grafica folosim limbajul de programare Java cu ajutorul mediului de programare NetBeans. 95

Pentru a crea un proiect in NetBeans trebuie sa urmam următorii pași : File – New Project – Java – Java Application – Next In cadrul ferestrei deschise putem sa stabilim numele proiectului (Project Name), locația proiectului si fișierul ce o sa conțină proiectul in sine, putem stabili locația librăriei, crearea clasei Main. Finish

96

Am obținut proiectul Biblioteca. In fereastra Project se găsesc toate fișierele programului astfel creat:

97

-

Source Packages - Sursele din proiect (.java)care sunt incluse in pachetele definite de către utilizator sau in pachetul implicit; Test Packages - Testarea surselor (.class); Libraries - Librariile corespunzatoare proiectului Test Libraries - Testarea librariilor.

-

-

In pagina din dreapta se observa codul sursa al fișierului Main.java. Modificările in codul sursa se fac numai sub rândul :„//TODO code applications logic here” Public class main { Public static void main (string[] args ) { //TODO code applications logic here System.out.println("BUN VENIT"); } } Compilarea codului sursă se poate face in mai multe moduri : Click dreapta pe fişierul main.java – compile sau F9 Meniul Run – Compile “Main.java” sau F9 In fereastra output o sa găsim următorul mesaj:

Pentru a construi fişierul executabil in java biblioteca.jar parcurgem următorii paşi: Run – Build Main Project sau F11. In fereastra Output vom avea:

Rularea programului se poate face urmînd următorii paşi: 98

-

Click dreapta pe fişierul main.java – Run File sau Shift + F6 Meniul Run – Run File sau Shift + F6

-

In fereastra output o sa găsim următorul mesaj:

Pentru a adăuga o noua fereastra, se intra in Projects – Source Packges – Biblioteca, click dreapta si se alege New – Jframe Form…

In fereastra nou aparută se alege numele clasei si locaţia . Finish.

99

A fost creata o noua clasa Primapagina.java. Este compusa dintr-un container de nivel înalt JFrame. In partea dreapta , in fereastra Palette găsim componente Swing, containere (JPanel, JTabbedPane, …) elemente atomice (JButton, JRadioButton, ), componente pentru editarea textului (JTextArea, JTextField, …), meniuri swing (JMenuBar, JMenu, JMenuItem, ..). Aceste componente Swing o sa ne ajute pentru a realiza interfata grafica a programului de gestionare a unei biblioteci.

Am adăugat elementele grafice la containerul JFrame si am obţinut imaginea de mai jos. In fereastra Inspector se pot vedea componentele adăugate .

După adăugarea elementelor grafice , definim acţiunea pe fiecare buton in parte. Click dreapta pe buton si selectam Events-Action-actionPerformed o sa ne duca in codul sursa al paginii respective unde definim acțiunea pe care trebuie sa o execute apăsarea pe butonul respectiv. 100

Închiderea paginii: private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: System.exit(0); }

Deschiderea unei alte pagini: private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: new Autentificare().setVisible(true); } Anularea continutului unor casete de tip JText sau JPasword: private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: jTextField1.setText(""); jPasswordField1.setText(""); }

101

6.3. Funcționarea programului ByblioTon
Programul ByblioTon, este un program destinat gestionarii cărţilor dintr-o biblioteca, in cadrul unei scoli, liceu sau pentru uzul personal. Tine evidenta cărţilor dintr-o biblioteca, a autorilor, editurilor cu care lucrează , a cititorilor care împrumută cărți din biblioteca respectiva. Lansarea programului in execuție ne întâmpina cu o fereastra unde avem posibilitatea sa de a ne autentifica si a intra in program, putem părăsi utilizării programului prin accesarea meniului ajutor. programul respectiv, sau afla date despre program si putem primii o mana de ajutor in vederea

Pentru a putea accesa programul , trebuie sa ne autentificam neapărat. File – Autentificare, ne deschide fereastra de autentificare in care trebuie introdus userul si parola. Daca datele introduse sunt corecte o sa se deschidă pagina principala a programului.

102

Pagina principala a programului conține un meniu intuitiv, prietenos, care ne poarta prin toate operațiunile de care avem nevoie pentru editarea unei cărti , al unui autor, al unei edituri , al unui cititor, modificarea lor, căutarea si ștergerea datelor introduse in program .

Pentru adăugarea unei cărți parcurgem următorii pași : Operațiuni – Carte - Adăugare Carte – completare câmpuri (Titlu, ISBN, An apariție, Ediția, Cuvinte Cheie). Pentru a completa câmpul Autor o sa trebuiască sa verificam daca ii avem deja adăugați. Apăsam butonul Căutare , o sa se deschidă pagina căutare autor, se

103

completează câmpurile Nume autor si/sau ID autor , se apasă butonul Căutare ce o sa returneze

in tabel, rezultatul găsit. Marcam rezultatul si prin apăsarea butonului Insert Autor, introducem autorul găsit in formularul de adăugare carte. Daca nu găsim nici un rezultat prin apăsarea butonului Adăugare Autor deschidem pagina de editare a autorilor. Completam câmpurile si

104

Adăugare Autor ne inserează autorul editat in baza de date. Ne întoarcem la pagina căutare autori , căutam autorul introdus de noi in baza de date, il selectam si prin apăsarea butonului Inserare Autor, adăugam un autor la cartea pe care vrem sa o introducem in baza de date. Pentru Editura , se procedează similar cu adăugarea de autor. Apăsam butonul Căutare, se deschide pagina de Căutare Editura – completam câmpurile ID Editura sau Nume Editura – Căutare. In tabelul de mai jos o sa observam rezultatul cautării. Daca nu apare nimic, o sa trebuiască sa introducem in baza de date editura. Adăugare Editura , o sa ne trimită in pagina de

introducere a unei nou edituri in baza de date. După completarea câmpurilor la apăsarea

105

butonului Adăugare Editura , o noua înregistrare o sa se facă in baza de date. In pagina Căutare Editura , verificam daca datele introduse s-au înregistrat, printr-o noua căutare. Returnarea rezultatului se face in tabelul de mai jos , se marchează editura si se apasă Inserare Editura. Aceasta acțiune are ca urmare completarea câmpului Editura in formularul de adăugare a cărții. După completarea tuturor câmpurilor, se poate apasă butonul Adăuga Carte, ce o sa aibă ca rezultat introducerea datelor de înregistrare a unei cărți in baza de date. Putem modifica datele de înregistrare a unei cărţi: Operații – Cărţi – Modificare Carte – Ne deschide pagina Căutare Carte , introducem datele si apăsăm Căutare. Marcam rezultatul

106

returnat , apăsam Modificare Carte , se deschide pagina Adăugare/Modificare Carte , editam modificările apărute si apăsam Modificare Carte. Pentru a şterge o carte din baza de date se parcurg următorii pași: Operațiuni – Carte – Ștergere carte – Căutare Carte – se introduc datele de căutare a cărţii – Căutare – se marchează, din tabelul, cartea pe care vrem sa o ștergem si butonul Ștergere Carte o sa elimine datele de înregistrare al cărții respective, din baza de date. Datele de înregistrare despre edituri se pot si ele modifica si șterge la fel ca si datele despre cărți si despre autori. Datele despre cititori , se pot adăuga, modifica, șterge si căuta după aproximativ aceleași operațiuni ca si datele despre cărţi. Despre cărți , putem afla de cat ori a fost împrumutata o anumita carte si de către cine, intrând in meniul Circulație – Istoric Carte. Completând datele de căutare a cărţii respective

107

Si apăsând butonul Caută, in tabelul de mai jos se vor observa toate împrumuturile si restituirile unei cărți. Pentru ca un cititor sa împrumute o carte trebuie sa facem următoarele operațiuni: Se intra in meniul principal, pe meniul Circulație – Împrumut carte – o sa se deschidă pagina Căutare Cititor – introducem datele cititorului respectiv, Căutare – dam click cu mausul pe cititorul respectiv si apăsam butonul Împumut. Se deschide pagina Împrumut Carte – Împrumuta

Se deschide pagina Căutare Carte – se introduc datele cărții respective, Căutare – se marchează cartea căutata si se apasă Împrumut- aceasta comanda o sa ne adauge cartea automat in tabelul paginii Împrumut Carte.

108

Pentru un cititor care dorește sa prelungească perioada de împrumut a cărții nu trebuie sa intram decât in pagina Împrumut Carte , se bifează cartea respectiva si se apasă Prelungire. Automat data restituirii se va schimba si o sa trebuiască sa o aducă peste 14 zile.

7.Concluzii
109

Interfața grafica pentru gestionarea unei biblioteci, denumita ByblioTon – Sunetul cărţilor sau armonia cărților – este destinata pentru bibliotecile de dimensiuni mici sau medii, bibliotecile școlilor generale, pentru licee, universități si pentru bibliotecile particulare. Este un program ușor de folosit, intuitiv, care nu cere resurse foarte multe pentru a fii rulat. Este un program construit pe baza tehnologiei Swing din Java si al unei baze de date in MySQL. Baza de date are rolul de a stoca informațiile referitoare la cărți, autori, cititori. Interfața grafica gestionează intrările si ieșirile din baza de date, Acest program, îndeplinește toate facilitățile pentru a fii folosit in cadrul școlilor. Cu mici îmbunătăţiri poate sa fie folosit si pentru genul de programe client-server, când un cititor poate sa acceseze de la distanta programul si sa afle ce cărţi trebuie sa aducă la biblioteca si pana când. Sa afle, de acasă, daca o sa găsească la scoală manualele sau culegerile de care are nevoie. Având in vedere ca programele folosite la dezvoltarea acestei interfețe grafice sunt gratuite – MySQL si NetBeans – costurile de producție sunt minime si automat este foarte accesibil si are un atu in plus fata de programele ce rulează pe piață sub diverse licențe. Utilizatorului final cat si celui ce face cunoștința pentru prima data cu acest program de gestionare, i se vor prezenta atât, un scurt istoric la evoluției bazei de date informatizate, cat si etapele premergătoare ce stau la baza conceperii programului. Capitolele lucrării, ce sunt structurate atent, cu elemente strict de baza, ce duc treptat la o cunoaștere facila a programului final BiblyoTon, ajuta la utilizarea acestuia atât in domeniul de uz personal cat si didactic școlar. Intr-o societate moderna, așa cum este cea in care trăim, marcata de utilizarea tehnologiilor la aproape orice nivel, cunoștințele de utilizare a programele de proiectare, creare si utilizare a bazelor de date informatizate au devenit indispensabile aproape in orice domeniu de gestionare ce tinde sa-si organizeze facil si prompt activitatea. BiblyoTon, fiind un program ce are la baza si funcționalitatea open – source, nu necesita costuri de licențiere, versiunile sau imbunatatirile nou apărute fiind publice si disponibile. Sistemul se poate adapta nevoilor utilizatorului, se poate personaliza, aducând asupra lui modificările dorite, necesare acestuia. Nefiind restrictiv in privința platformele de lucru: Windows, Linux, Unix, BiblyoTon poate fi instalat si pe un sever si poate fi accesat din orice sistem de operare prin intermediul unui browser, totodată oferind baza pentru dezvoltarea unei biblioteci digitale cat si asigurarea unui management al documentelor si al altor materiale in format electronic. Dezvoltarea si 110

administrarea conturilor utilizatorilor, ce conțin informații personale, date de contact, istoricul împrumuturilor si situația la zi, este posibila prin accesarea acestora cu ușurința. Intr-o accepțiune moderna bibliotecile digitale nu sunt numai o simpla replica a unor biblioteci clasice, ci reprezintă un mediu integrat de generare, stocare, gestionare si difuzare de conținut digital. Nu mai trebuie demonstrat că utilizarea calculatorului şi-a dovedit din plin eficienţa în gestionarea si organizarea informaţiei. În biblioteci, centre de informare, muzee moderne, nenumărate procese se desfăşoară asistate de calculator. Întrucât informaţia circulă tot mai repede şi proliferează spectaculos, sursele de informare trebuie să ţină pasul cu dinamica producţiei, ceea ce face necesară aducerea lor la zi în permanenţă. Diversificarea utilizatorilor creează şi niveluri diversificate ale informării, fiecăruia corespunzându-i şi surse de informare predilecte. Intr-o societate în continuă schimbare, trebuie să ne adaptăm continuu cerinţelor ei, să ne adaptăm şi să acceptăm schimbarea, să ne obişnuim cu noua tehnică şi să o folosim pentru uşurarea propriei munci precum şi să venim în ajutorul utilizatorilor de informaţie.

111

Sign up to vote on this title
UsefulNot useful