lucrare disertatie

76
UNIVERSITATEA TEHNICĂ DIN CLUJ-NAPOCA Şcoala academică postuniversitară Informatică aplicată şi programare ORACLE – Evidenţa internărilor din unităţile spitaliceşti Lucrare de disertaţie Ioana Marinela Iclozan (Năndrean):

Upload: nandreanioana

Post on 01-Dec-2015

155 views

Category:

Documents


7 download

DESCRIPTION

Baze de date- Oracle

TRANSCRIPT

Page 1: Lucrare disertatie

UNIVERSITATEA TEHNICĂ DIN CLUJ-NAPOCA

Şcoala academică postuniversitară Informatică aplicată şi programare

ORACLE – Evidenţa internărilor din unităţile spitaliceşti

Lucrare de disertaţie

Ioana Marinela Iclozan (Năndrean):

2010

Page 2: Lucrare disertatie

CAPITOLUL 1.

TEORIA BAZELOR DE DATE RELAŢIONALE

1 MODELUL RELAŢIONAL

Modelul relaţional a fost propus de catre IBM şi a revoluţionat reprezentarea datelor făcând trecerea la generatia a doua de baze de date. Modelul este simplu, are o solidă fundamentare teoretică fiind bazat pe teoria seturilor (ansamblurilor) şi pe logica matematică. Pot fi reprezentate toate tipurile de structuri de date de mare complexitate, din diferite domenii de activitate. Modelul relaţional este definit prin: structura de date, operatorii care acţioneaza asupra structurii si restricţiile de integritate. 1) Conceptele utilizate pentru definirea structurii de date sunt: domeniul, tabela (relaţia), atributul, tuplul, cheia şi schema tabelei. Domeniul este un ansamblu de valori caracterizat printr-un nume. El poate fi explicit sau implicit. Tabela/relaţia este un subansamblu al produsului cartezian al mai multor domenii, caracterizat printr-un nume, prin care se definesc atributele ce aparţin aceleaşi clase de entităţi. Atributul este coloana unei tabele, caracterizată printr-un nume. Cheia este un atribut sau un ansamblu de atribute care au rolul de a identifica un tuplu dintr-o tabela. Tipuri de chei: primare/alternate, simple/comune, externe. Tuplul este linia dintr-o tabela şi nu are nume. Ordinea liniilor (tupluri) şi coloanelor (atribute) dintr-o tabelă nu trebuie să prezinte nici-o importanţă. Schema tabelei este formată din numele tabelei, urmat între paranteze rotunde de lista atributelor, iar pentru fiecare atribut se precizează domeniul asociat. Schema bazei de date poate fi reprezentată printr-o diagramă de structură în care sunt puse în evidenţă şi legăturile dintre tabele. Definirea legăturilor dintre tabele se face logic construind asocieri între tabele cu ajutorul unor atribute de legatură. Atributele implicate în realizarea legăturilor se găsesc fie în tabelele asociate, fie în tabele distincte construite special pentru legături. Atributul din tabela iniţială se numeşte cheie externă, iar cel din tabela finală este cheie primară. Legăturile posibile sunt 1:1, 1:m, m:n. Potenţial, orice tabelă se poate lega cu orice tabelă, după orice atribute. Legaturile se stabilesc la momentul descrierii datelor prin limbaje de descriere a datelor (LDD), cu ajutorul restricţiilor de integritate. Practic, se stabilesc şi legături dinamice la momentul execuţiei. 2) Operatorii modelului relaţional sunt operatorii din algebra relaţională şi operatorii din calculul relaţional. Algebra relaţională este o colecţie de operaţii formale aplicate asupra tabelelor (relaţiilor), şi a fost conceputa de E.F.Codd. Operaţiile sunt aplicate în expresiile algebrice relaţionale care sunt cereri de regăsire. Acestea sunt compuse din operatorii relaţionali şi operanzi. Operanzii sunt întotdeauna tabele (una sau mai multe). Rezultatul evaluării unei expresii relaţionale este format dintr-o singură tabelă. Algebra relaţională este prin definiţie neprocedurală (descriptivă), iar calculul relaţional permite o manieră de cautare mixtă (procedurală/neprocedurală). Calculul relaţional se bazează pe calculul predicatelor de ordinul întâi (domeniu al logicii) şi a fost propus de E.F. Codd. Predicatul este o relaţie care se stabileşte între anumite elemente şi care poate fi confirmată sau nu. Predicatul de ordinul 1 este o relaţie care are drept argument variabile care nu sunt predicate. Variabila poate fi de tip tuplu (valorile sunt dintr-un tuplu al unei tabele) sau domeniu (valorile sunt dintr-un domeniu al unei tabele). Cuantificatorii (operatorii) utilizaţi în

2

Page 3: Lucrare disertatie

calculul relaţional sunt: universal ( ) şi existenţial ( ). Construcţia de bază în calculul relaţional este expresia relaţională de calcul tuplu sau domeniu (funcţie de tipul variabilei utilizate). Expresia relaţională de calcul este formată din: operaţia de efectuat, variabile (tuplu respectiv domeniu), condiţii (de comparaţie, de existenţă), formule bine definite (operanzi-constante, variabile, funcţii, predicate; operatori), cuantificatori. Pentru implementarea acestor operatori există comenzi specific în limbajele de manipulare a datelor (LMD) din sistemele de gestiune a bazelor de date relaţionale (SGBDR). Aceste comenzi sunt utilizate în operaţii de regăsire (interogare). După tehnica folosită la manipulare, LMD sunt bazate pe:

- calculul relational (QUEL în Ingres, ALPHA propus de Codd);- algebra relaţională (ISBL, RDMS);- transformare (SQL, SQUARE);- grafica (QBE, QBF).

3) Restricţiile de integritate ale modelului relaţional sunt structurale si comportamentale.

Restricţiile structurale sunt: • Restricţia de unicitate a cheii • Restricţia referenţială • Restricţia entităţii.Cele trei restricţii de mai sus sunt minimale.

Restricţiile de comportament sunt cele care se definesc prin comportamentul datelor şi ţin cont de valorile din BDR: • Restricţia de domeniu. • Restricţii temporareRestricţiile de integritate suportate de Oracle sunt: • NOT NULL nu permite valori NULL în coloanele unei tabele; • UNIQUE nu sunt permise valori duplicat în coloanele unei tabele; • PRIMARY KEY nu permite valori duplicate sau NULL în coloana sau coloanele definite astfel; • FOREIGN KEY presupune ca fiecare valoare din coloană sau setul de coloane definite astfel să aibă o valoare corespondentă identică în tabela de legatură, tabelă în care coloana corespondentă este definită cu restricţia UNIQUE sau PRIMARY KEY; • CHECK elimină valorile care nu satisfac anumite cerinţe (condiţii) logice. Termenul de chei (keys) este folosit pentru definirea câtorva categorii de constrângeri şi sunt: primary key, unique key, foreign key, referenced key. Se consideră că modelul relaţional are o serie de limite cum ar fi: simplitatea modelului îl face dificil de aplicat pentru noile tipuri de aplicaţii (multimedia, internet etc.); nu asigură o independenţă logică totală a datelor de aplicaţie; poate creşte redundanţa datelor.

1.1. BAZE DE DATE RELAŢIONALE

Bazele de date relaţionale (BDR) utilizează modelul de date relaţional şi noţiunile aferente. BDR au o solidă fundamentare teoretică, în special prin cercetările de la IBM conduse de E.F.Codd. BDReste un ansamblu organizat de tabele (relaţii) împreună cu legăturile dintre ele. Atunci când dorim să realizăm o bază de date relaţională trebuie să ştim clar ce avem de făcut, adică să stabilim obiectivele activităţii noastre. În acest sens, câteva dintre cele mai importante obiective sunt: • Partiţionarea - aceleaşi date trebuie să poată fi folosite în moduri diferite de către diferiţi utilizatori; • Deschiderea - datele trebuie să fie uşor adaptabile la schimbările care pot apărea

3

Page 4: Lucrare disertatie

(actualizarea structurii, tipuri noi de date etc.); • Eficienţa - stocarea şi prelucrarea datelor, care trebuie să se facă la costuri cât mai scăzute, costuri care să fie inferioare beneficiilor obţinute; • Reutilizarea - fondul de date existent trebuie să poata fi reutilizat în diferite aplicatii informatice; • Regăsirea

• Accesul - modul de localizare a datelor • Modularizarea - realizarea BDR trebuie să se poată face modular pentru

generalitate şi posibilitatea lucrului în echipă; • Protecţia

• Redundanţa – implementarea unui model de date pentru baze de date şi utilizarea unei tehnici de proiectare a BDR.

• Independenţa

1.1.1. EXEMPLE DE SISTEME DE GESTIUNE A BAZELOR DE DATE RELAŢIONALE

DB2 Este realizat de firma IBM. Sistemul respectă teoria relaţională, este robust şi se bazează pe SQL standard. Permite lucrul distribuit şi are modul de optimizare a regăsirii. Informix. Este realizat de firma Informix, respectă teoria relaţională şi permite lucrul distribuit. Progress. Este realizat de firma Progress Software. Are limbaj propriu (Progress 4GL), dar suportă şi SQL. Rulează pe o gamă largă de calculatoare sub diferite sisteme de operare. SQL Server. Este realizat de firma Microsoft. Se bazează pe SQL şi rulează în arhitectura client/server. Ingress II . Este realizat de firma Computer Associates. Este un SGBDR complet, implementează două limbaje relaţionale (întâi QUEL şi apoi SQL) şi este suportat de diferite sisteme de operare (Windows, UNIX). Visual FoxPro Este realizat de firma Microsoft. Are un limbaj procedural propriu foarte puternic, o extensie orientată obiect, programare vizuală şi nucleu extins de SQL. Access Este realizat de firma Microsoft. Se bazează pe SQL, are limbajul procedural gazdă (Basic Access) şi instrumente de dezvoltare. Paradox. Este realizat de firma Borland. Are limbaj procedural propriu (PAL) şi suportă SQL. Oracle Este realizat de firma Oracle Corporation USA. Sistemul este complet relaţional, robust, se bazează pe SQL standard extins. Oracle Database Express Edition este un server de baze de date relaţionale. Într-o bază de date relaţională datele sunt păstrate în fişiere de date. Un fişier conţine articole având fiecare aceeaşi structură, definită la crearea sa. Structura articolelor unui fişier de date este definită la crearea sa, prin precizarea câmpurilor pe care le va conţine. Un câmp se caracterizează prin nume, tipul informaţiei conţinute, lungime şi numărul de zecimale (pentru câmpuri numerice). Un server Oracle XE operează cu o singură bază de date. Administratorul bazei de date crează conturi ale

4

Page 5: Lucrare disertatie

utilizatorilor cărora le atribuie drepturile necesare operării în interiorul bazei Oracle XE. Un astfel de utilizator devine astfel proprietarul unui subdomeniu inclus în baza Oracle XE denumit decătre autorii aplicaţiei "schemă" (engl. schema). După înregistrarea contului, beneficiarul acestuia poate realiza infrastructura pe care se va baza aplicaţia sa : tabele, interogări, vederi, proceduri, etc.. Domeniile diferitilor utilizatori sunt în principiu complet separate, un utilizator având însă posibilitatea de a da si altor utilizatori drepturi de acces la componentele domeniului său. Dimensiunea bazei de date administrate de Oracle XE este limitată la 4 GO (4 gigaocteţi).

CAPITOLUL 2.

FACILITĂŢILE ŞI ARHITECTURA SISTEMULUI ORACLE

1. EVOLUŢIA ŞI FACILITĂŢILE SISTEMULUI ORACLE

Sistemul Oracle este realizat de firma Oracle Corporation care a fost înfiinţată în anul 1977 în SUA - California şi acum este cel mai mare furnizor de software de gestiunea datelor. Acesta este operaţional pe toată gama de calculatoare (micro, mini, mainframe) sub diverse sisteme de operare. Prima versiune de SGBD Oracle a fost realizată la sfârşitul anilor '70 respectând teoria relaţională. În cadrul sistemului a fost implementat de la început limbajul relaţional SQL pe care l-a dezvoltat ulterior faţă de versiunea standard rezultând SQL*Plus. Începând cu versiunea 5.0 SGBD Oracle are următoarele facilităţi suplimentare: funcţionează în arhitectura client/server; are limbaj procedural propriu PL/SQL; are precompilatoare ca interfaţă cu limbajele universale. În iunie 1997 s-a lansat SGBD Oracle versiunea 8.0 inclusiv în România. În noiembrie 1998 s-a lansat SGBD Oracle 8i ca sistem de baze de date pe Internet. Ulterior a fost lansat sistemul Oracle 9i care a marcat trecerea la o noua generaţie de servicii internet. El este mai mult decât un suport pentru baze de date deoarece oferă o infrastructură completă de software pentru afaceri electronice (e-business) şi rulează pe o varietate de sisteme de calcul şi de operare: SUN-SOLARIS, HP-UX, IBM-AIX, PC_WINDOWS, XX- LINUX. Componenta Oracle WebDB a evoluat în Oracle Portal. Oracle 9i DATABASE are faţă de versiunea anterioară asigurată o protecţie ridicată şi automatizată, iar costul administrării bazei de date scade în mod drastic. Oracle 9i REAL APPLICATION CLUSTERS (RAC) se bazează pe o nouă arhitectură de BD numită îmbinare ascunsă (Cache Fusion). Aceasta este o noua generaţie de tehnologie de clustere. Conform acestei arhitecturi la adaugarea unui calculator într-o retea cu BD Oracle, clusterele se adaptează automat la noile resurse, fară să fie necesară redistribuirea datelor sau rescrierea aplicaţiei. Posibilitatea apariţiei unei erori la o configuraţie cu 12 calculatoare sub Oracle 9i RAC este foarte mică, estimată ca durată în timp la cca 100.000 de ani. În Oracle 9i APPLICATION SERVER se pot creea şi utiliza aplicaţii Web care sunt foarte rapide şi permit integrarea serviciilor de Internet. Oracle 9i DEVELOPER SUITE este un mediu complet pentru dezvoltarea aplicaţiilor tip afaceri electronice (e-business) şi tip Web. El se bazează pe tehnologiile Java şi XML şi permite

5

Page 6: Lucrare disertatie

personalizarea (Oracle Personalization). În anul 2003 a fost lansată versiunea Oracle 10g care adaugă noi facilităţi sistemului Oracle 9i.

1.1. ARHITECTURA SISTEMULUI ORACLE

Componentele care formează arhitectura de bază Oracle sunt dispuse într-o configuraţie client/server. Aceste componente sunt plasate pe calculatoare diferite într-o reţea asigurând functionalităţi specifice, astfel: serverul asigură memorarea şi manipularea datelor, precum şi administrarea bazei de date, iar clientul asigură interfaţa cu utilizatorul şi lansează aplicaţia care accesează datele din baza de date.

Figura 2.1 Arhitectura Oracle

Arhitectura Oracle se încadrează în tendinţele actuale şi anume este structurată pe trei niveluri: nucleul, interfeţele şi instrumentele de întreţinere.

Nucleul Oracle conţine componentele care dau tipul relaţional pentru SGBD Oracle: limbajul relaţional de regăsire SQL şi limbajul procedural propriu PL/SQL. Interfeţele sunt componentele care permit dezvoltarea aplicaţiilor cu BD. Instrumentele sunt componente destinate întreţinerii şi bunei funcţionări a unei BD Oracle.

1.1.1. ORACLE SERVER

Oracle Server (OS) permite managementul informaţiilor organizate în baze de date, astfel încât se asigură accesul mai multor utilizatori în mod concurenţial la aceleaşi date, oferind facilităţi de prevenire a accesului neautorizat şi de restaurare a datelor după producerea unor erori. OS este un

6

Page 7: Lucrare disertatie

sistem relaţional-obiectual de management a bazelor de date, care permite o abordare deschisă, integrată şi cuprinzătoare a managementului informaţiilor. OS constă dintr-un cuplu format dintr-o bază de date şi o instanţă Oracle.

A. O bază de date Oracle este o colecţie unitară de date, având o structură logică şi una fizică putând avea doua stări: open (accesibilă) şi close (inaccesibilă).

1) Structura logică ale unei baze de date este formată din tabelele spaţiu (tablespaces), schema de obiectelor bazei de date, blocurile de date, extensiile si segmentele. Tabelele spaţiu sunt unităţile logice de memorie în care este împărţită o bază de date şi pot fi tabele spaţiu de sistem şi tabele spaţiu de utilizator. Fişierele de date sunt structurile de memorie specifice unui sistem de operare pe care rezidă tabelele spaţiu ale unei baze de date. Schema este o colecţie de obiecte, iar schema de obiecte este o structură logică ce se referă direct la datele unei baze de date (tabele, vederi, secvenţe, proceduri memorate, sinonime, indecsi, clustere şi link-uri de bază de date). Blocurile de date, extensiile şi segmentele sunt elemente de control eficient al spaţiului de memorie externă pe disc aferent unei baze de date. Blocul de date este unitatea de memorie cea mai mică manipulată de SGBD Oracle, iar marimea acestuia masurată în bytes se defineşte la momentul creerii bazei de date. Extensia este formată din mai multe blocuri de date contigue. Segmentul este format din mai multe extensii. Segmentele pot fi: segmente de date (pentru memorarea datelor unei tabele), segmente de indecsi, segmente rollback (folosite pentru memorarea informaţiilor necesare pentru recuperarea datelor unei baze de date sau anularea unei tranzacţii) şi segmente temporare (folosite pentru prelucrarea instrucţiunilor SQL). 2) Structura fizică este definită de un set de fişiere specifice sistemului de operare pe care rezidă SGBD Oracle, folosite pentru memorarea structurilor logice ale bazei de date şi pentru păstrarea unor informaţii tehnice de control. Aceste fişiere sunt: fişiere de date (Data files), fişiere Redo log (Redo Log files) şi fişiere de control (Control files). Fişierele de date (Data files) conţin datele unei baze de date, sub forma structurilor logice ale acesteia (tabele, vederi, secvenţe, proceduri memorate, sinonime, indecsi, clustere şi link-uri de bază de date). Fişierele Redo Log (Redo Log files) sunt folosite pentru memorarea tuturor schimbărilor de date produse asupra unei baze de date, astfel încât dacă se întâmplă o cădere de curent să se prevină distrugerea datelor bazei de date. Fişierele de control (Control files) sunt folosite pentru memorarea informaţiilor necesare pentru controlul structurii fizice a unei baze de date (numele bazei de date, numele şi locaţiile fişierelor de date, data creerii bazei de date etc).

B. Instanţa Oracle (Oracle instance) este combinaţia logică dintre structurile de memorie internă (SGA - system global area, PGA – program global area)şi procesele Oracle de bază activate la momentul pornirii unei baze de date. 1) SGA este o regiune partajabilă de memorie care conţine datele şi informaţiile necesare unei instanţe Oracle. 2) PGA este zona de memorie care conţine datele şi informaţiile de control ale unui proces server.

7

Page 8: Lucrare disertatie

3) Procesul este un mecanism al sistemului de operare care poate executa o serie de paşi (instructiuni).

CAPITOLUL 3.

ELEMENTELE DE BAZĂ ALE LIMBAJULUI SQL

În 1992 ANSI (American National Standards Institute) a definitivat varianta standard a unui limbaj destinat sistemelor de gestiune a bazelor de date denumit Structured Query Language, prescurtat SQL. Frazele SQL permit crearea, actualizarea, interogarea şi distrugerea bazelor de date relaţionale. Desi toate S.G.B.D. folosesc SQL, adesea ele implementează si funcţii care nu există în standard. Comenzile de bază ale limbajului SQL care sunt Create, Alter, Select, Insert, Update, Delete şi Drop sunt suportate de toate sistemele de gestiune de baze de date şi permit realizarea tuturor activităţilor majore legate de crearea şi exploatarea bazelor de date relaţionale. Cuvintele cheie ale limbajului SQL pot fi scrise atât cu litere mici cât şi cu majuscule.

1. INTRODUCEREA COMENZILOR SQL FOLOSIND INTERFAŢA GRAFICĂ

După conectare se selectează SQL Commands / Enter Command.

8

Page 9: Lucrare disertatie

Comenzile introduse în fereastra SQL Commands pot fi terminate prin ';' ca în MySQL de exemplu sau se poate chiar omite caracterul terminal. Astfel pentru suprimarea tabelului cafea se poate scrie:

drop table cafea;sau pur si simpludrop table cafea

efectul fiind acelaşi. Comenzile SQL pot fi memorate individual apăsând butonul Save:

Comenzile memorate pot fi reexecutate prin selectare cu mouse-ul (dublu clic):

9

Page 10: Lucrare disertatie

1.1. TIPURI DE DATE SUPORTATE DE ORACLE

a. Şiruri de caractere Oracle defineste patru tipuri de date:- VARCHAR2 - pentru şiruri de caractere de lungime variabilă,- NVARCHAR2 pentru şiruri de caractere de lungime variabilă în format UNICODE (16 biţi / caracter),- CHAR - pentru şiruri de caractere având lungime fixă,- NCHAR - pentru şiruri de caractere având lungime fixă, în format UNICODE. Indiferent de tip, la declararea unui câmp trebuie precizată lungimea:

nume varchar2(50)Pentru VARCHAR2 lungimea specificată este cea maximă admisă în timp ce pentru CHAR ea va fi efectiv utilizată, şirurile de lungime mai mică fiind completate la dreapta cu spaţii. Rezultă că VARCHAR2 este mai eficient. b. Date numerice Datele numerice pot fi declarate în Oracle folosind unul dintre tipurile următoare:- NUMBER - pentru numere zecimale,- BINARY_FLOAT - pentru numere reale (memorate fără conversie în baza 10)- BINARY_DOUBLE- pentru numere reale în dublă precizie (memorate fără conversie). Cel mai frecvent se foloseste tipul NUMBER. Pentru declararea unei date de tip NUMBER se poate scrie:

înălţime number(3)sau,

înălţime number(3,0) Pentru numere care au o parte întreagă şi una zecimală se scrie:

pret NUMBER(7,2)însemnând reprezentarea câmpului pret folosind 7 poziţii zecimale, ultimele două fiind folosite pentru partea reală. BINARY_FLOAT şi BINARY_DOUBLE sunt tipuri recomandate în cazul în care datele astfel reprezentate sunt folosite la calcule mai complicate.

c. Tipuri pentru timp şi dată calendaristică Pentru declararea câmpurilor care vor păstra data calendaristică sau timpul, Oracle foloseşte tipurile DATE şi TIMESTAMP.

10

Page 11: Lucrare disertatie

d. Tipuri pentru memorarea imaginilor Pentru declararea câmpurilor destinate păstrării în baza de date a imaginilor, Oracle foloseste tipurile CLOB sau BLOB.

1.1.1. CREAREA TABELELOR ÎN ORACLE XE

Comanda CREATE TABLE

Comanda CREATE TABLE serveşte la crearea unui nou tabel şi la descrierea câmpurilor acestuia. Ea are formatul general:

CREATE TABLE nume(nume_câmp tip_câmp [(marime [,precizie])]

[NULL | NOT NULL][PRIMARY KEY | UNIQUE]

[,nume_câmp tip_câmp [(marime [,precizie])][NULL | NOT NULL]

)

Crearea tabelelor va fi realizată mai uşor folosind interfaţa serverului Oracle XE. În cazul în care în momentul creării unui tabel se impun restricţii asupra câmpurilor, se declară chei străine sau se declară o cheie primară, fraza SQL corespunzătoare va conţine un număr de restricţii introduse folosind cuvântul rezervat "constraints".

CREATE TABLE "DEMO_ORDERS" ( "ORDER_ID" NUMBER NOT NULL ENABLE, "CUSTOMER_ID" NUMBER NOT NULL ENABLE, "ORDER_TOTAL" NUMBER(8,2), "ORDER_TIMESTAMP" DATE, "USER_ID" NUMBER, CONSTRAINT "DEMO_ORDER_PK" PRIMARY KEY ("ORDER_ID") ENABLE, CONSTRAINT "DEMO_ORDER_TOTAL_MIN" CHECK (order_total >= 0) ENABLE, CONSTRAINT "DEMO_ORDERS_CUSTOMER_ID_FK" FOREIGN KEY ("CUSTOMER_ID") REFERENCES "DEMO_CUSTOMERS" ("CUSTOMER_ID") ENABLE,

11

Page 12: Lucrare disertatie

CONSTRAINT "DEMO_ORDERS_USER_ID_FK" FOREIGN KEY ("USER_ID") REFERENCES "DEMO_USERS" ("USER_ID") ENABLE

)

În fraza SQL afişată denumirile câmpurilor, constrângerilor sau denumirea tabelului apar între ghilimele. Această scriere permite folosirea de denumiri conţinând spaţii (de evitat!). Dacă denumirile nu pot da naştere la confuzii, ghilimelele pot fi omise. Cele patru constrângeri declarate se referă la cheia primară, limitarea unei valori şi declară două câmpuri ca fiind chei străine, precizând şi tabelele legate. În primul exemplu cheia primară a fost declarată adăugând descrierii câmpului ID_regiune cuvintele PRIMARY KEY.

Comanda DROP TABLE

Comanda DROP TABLE permite suprimarea unui tabel. Sintaxa comenzii este:DROP TABLE Nume_tabel

Pentru a da comanda folosind interfaţa grafică se selectează succesivObject Browser / Browse / Tables, se selectează apoi tabelul şi se apasă butonul Drop:

Comanda SELECT

12

Page 13: Lucrare disertatie

Comanda SELECT creează o mulţime de selecţie. Aceasta poate conţine un articol, mai multe articole sau niciunul. Articolele din mulţimea de selecţie conţin numai câmpurile indicate de programator. Din acest punct de vedere se poate considera că SELECT crează un subtabel conţinând numai informaţiile specificate. Câmpurile înregistrărilor mulţimii de selecţie pot proveni dintr-un tabel sau din mai multe tabele legate. Comanda SELECT are formatul general:

SELECT [DISTINCT] coloana1 [,coloana2]FROM tabel_1[,tabel_2, ...]

[WHERE condiţii][GROUP BY listă-coloane]

[HAVING conditii][ORDER BY listă-coloane [ASC | DESC] ]

Dintre cele 5 clauze ale comenzii SELECT numai clauza FROM este obligatorie. Fiecare dintre clauze are la rândul ei reguli şi parametri pentru construcţie, făcând din SELECT cea mai complexă comandă a limbajului SQL. În frazele SELECT şirurile de caractere se pun între caractere ' (apostrof). A. Selectarea dintr-un singur tabel Exemple fundamentale:SELECT Nume, Prenume FROM cititorSELECT * FROM cititorSELECT * FROM cititor WHERE nume = 'Popescu'SELECT nume, prenume, adresa FROM cititor WHERE nume LIKE 'Po%'SELECT Nume, Prenume FROM cititor ORDER BY Nume Clauza WHERE permite limitarea mulŃimii de selecŃie prin introducerea unei condiŃii care specifică înregistrările căutate. În cazul selectării din mai multe tabele, această clauză poate fi folosită si pentru a introduce legăturile dintre tabele. La scrierea condiŃiei se pot folosi operatorii logici AND, OR sau NOT precum si operatorii relaŃionali: = Egal > Mai mare < Mai mic >= Mai mare sau egal

<= Mai mic sau egal<> sau != Diferit de

LIKE - LIKE permite selectarea liniilor care conţin în câmpul testat şiruri de caractere în care se regăseşte o succesiune de caractere precizată. Pentru definirea

succesiunii de caractere căutată se poate folosi caracterul generic "%". De exemplu clauza WHERE nume LIKE 'Po%' va permite selectarea liniilor în care nume = Pop şi nume=Popescu. Clauza

WHERE prenume LIKE '%a' permite selectarea tuturor liniilor în care prenumele se termină în "a". Exemple:SELECT * FROM cititor WHERE nume = 'Popescu' AND prenume='Mihai'SELECT * FROM cititor WHERE nume = 'Popescu' OR nume='Mihai'SELECT * FROM cititor WHERE nume = 'Popescu' AND prenume IN('Ioan','Vasile','Grigore')IN specifică o mulţime căreia trebuie să-i aparţină câmpul specificat (prenume).SELECT * FROM cititor WHERE nume = 'Popescu' AND data_naşteriiBETWEEN '12-MAY-1968' AND '29-MAY-1980'

13

Page 14: Lucrare disertatie

Clauza BETWEEN permite definirea unui interval căruia trebuie să-i aparţină câmpul specificat (data_naşterii). Clauza ORDER BY serveşte la impunerea ordinii de afişare a înregistrărilor mulţimiide selecţie. Ordonarea poate fi realizată după valorile unuia sau a mai multor câmpuri, crescător (ASC) sau descrescător (DESC). În cazul în care se folosesc mai multe câmpuri, acestea sunt separate prin virgulă.

SELECT * FROM Cititor ORDER BY Nume,Prenume,ID_cititorSELECT * FROM Angajati ORDER BY salar DESC, Nume ASC, Prenume ASC

Clauza DISTINCT permite realizarea unei mulŃimi de selecŃie care conŃine înregistrări distincte, care diferă prin cel puŃin o valoare a unui câmp. De exemplu :

SELECT DISTINCT Localitate FROM cititor Ultima frază va provoca afisarea numelor localităŃilor în care domiciliază cititorii. Fără clauza DISTINCT, numele orasului Cluj-Napoca ar fi fost repetat de mai multe ori. Clauza GROUP BY permite gruparea înregistrărilor după valoarea unui câmp.

Exemplul 1:

SELECT Localitate, COUNT(*) as Nr_Cititori FROM Cititor GROUP BY Localitate În cazul în care se realizează o grupare, fiecare dintre liniile mulţimii de selecţie se referă la un grup de înregistrări şi nu la înregistrări simple. În exemplul precedent, GROUP BY Localitate precizează câmpul după care se realizează gruparea. Înafara valorii câmpului după care se face gruparea, în astfel de situaţii liniile mulţimii de selecţie pot conţine rezultatul aplicării unor funcţii matematice asupra articolelor care formează grupul (suma valorilor dintr-un câmp, media valorilor, valoarea maximă sau minimă, numărul de articole care formează grupul etc). Pentru câmpurile care vor conţine rezultatul aplicării unor funcţii se recomandă folosirea clausei AS nume pentru atribuirea unui nume relevant coloanei respective. În exemplul dat s-a afişat rezultatul funcţiei COUNT(*), care numără înregistrările din grup. Funcţiile care pot fi apelate pentru câmpuri numerice sunt prezentate în tabelul de mai jos.

MIN returnează cea mai mică valoare dintr-o coloană (câmp numeric)MAX returnează cea mai mare valoare dintr-o coloană (câmp numeric)

SUM returnează suma valorilor numerice dintr-o coloană (câmp numeric)AVG returnează media valorilor dintr-o coloană (câmp numeric)

COUNT returnează numărul de valori dintr-o coloanăCOUNT DISTINCT returnează numărul de valori distincte dintr-o coloană

Exemplul 2:

SELECT Sectie, MAX(salar) as Sal_Max FROM Angajati GROUP BY Sectie Se pot însă aplica aceleaşi funcţii şi întregului fişier, fără gruparea articolelor, caz în care mulţimea de selecţie va conţine o singură înregistrare:

SELECT AVG(salar) FROM AngajaţiSELECT AVG(salar) FROM Angajaţi WHERE funcţie='Zidar'

SELECT COUNT(*) FROM Cititor Clauza HAVING serveşte la precizarea unui filtru care se aplică grupurilor de articole, dacă este prezentă clauza GROUP BY.

Exemplu:

14

Page 15: Lucrare disertatie

SELECT Sectie, AVG(Salar) FROM Angajaţi GROUP BY Secţie HAVING AVG(Salar) > 500 Dacă în fraza SELECT lipseşte clauza GROUP BY, folosirea clauzei HAVING nu sejustifică, ea având acelaşi efect ca şi clauza WHERE. O situaţie aparte prezintă comenzile SELECT care nu realizează o mulţime de selecţie ci un calcul matematic. În acest caz from nume_tabel va fi înlocuit prin from dual, ca în exemplul următor:

Cuvântul rezervat dual astfel folosit permite respectarea sintaxei comenzii SELECT.

B. Selectarea din mai multe tabele

Principial o bază de date relaţională presupune repartizarea datelor în mai multe tabele. Aşa cum s-a văzut deja, acest mod de stocare permite eliminarea informaţiilor redondante. Pentru a găsi articolele dintr-un tabel legate de o înregistrare din alt tabel trebuie însă indicată în frazele SELECT condiţia de legătură dintre cele două tabele. Exemple:

SELECT Edituri.Nume, Carti.Titlu, Carti.Anul FROM Edituri, Carti WHERENume='Minerva' AND Edituri.CodE=Carti.CodE

A doua condiţie conţinută în clauza WHERE este cea care leagă tabelele Edituri si Carti.Limbajul SQL permite înlocuirea unei mulţimi care contribuie la selecţie printr-o altă frază SELECT, ca în exemplul următor.

SELECT Edituri.Nume, Carti.Titlu, Carti.Anul FROM Edituri, Carti WHERENume='Minerva' AND Edituri.CodE=Carti.CodE AND Titlu.Data IN (SELECT

Data FROM Carti WHERE Data BETWEEN '12-MAY-1975' AND '29-MAY-1980') Odată cu standardizarea limbajului SQL, pentru introducerea legăturilor stabilite între tabele prin definirea de chei primare şi străine s-a definit şi o altă modalitate, respectiv clauza JOIN. Folosind JOIN, exemplul anterior poate fi scris astfel:

SELECT Edituri.Nume, Carti.Titlu, Carti.AnulFROM Edituri INNER JOIN Carti ON Edituri.CodE=Carti.CodE

WHERE Nume='Minerva'

15

Page 16: Lucrare disertatie

Clauza JOIN este însă şi soluţie într-o altă situaţie, respectiv când într-un tabel se acceptă pentru o cheie străină valori nule. Un exemplu simplu este cel al tabelelor Angajati şi Soti prezentate în continuare.

Dintre angajaţii din primul tabel doi sunt căsătoriţi, în cazul lor ID_SOT are valori nenule.Dacă se doreste realizarea unei mulţimi de selecţie care să cuprindă angajaţii, iar pentru cei căsătoriţi numele şi prenumele soţului/soţiei, fraza SELECT ar putea fi următoarea:

select Angajati.Nume, Angajati.Prenume,Soti.Nume_prenumefrom Angajati, Soti where Angajati.ID_SOT=SOTI.ID_SOT

Rezultat:

Rezultatul nu este cel dorit deoarece prin condiţia pusă sunt excluşi din mulţimea de selecţie angajaţii necăsătoriţi. Soluţia este oferită de clauza LEFT OUTER JOIN:

select Angajati.Nume, Angajati.Prenume,Soti.Nume_prenume from Angajati left outer join Soti on Angajati.ID_SOT=SOTI.ID_SOT

Rezultatul va cuprinde toate liniile din primul table, iar pentru liniile din primul tabel care au corespondent în al doilea tabel, va include şi informaţiile corespunzătoare din al doilea tabel.

16

Page 17: Lucrare disertatie

Similar se poate folosi clauza RIGHT OUTER JOIN pentru includerea tuturor înregistrărilor din al doilea tabel şi selectarea din primul doar a celor care satisfac relaţia de legătură.

C. Utilizarea parametrilor

SQL permite ca la scrierea comenzii SELECT să se folosească parametrii. Valorile acestora sunt cerute într-o fereastră separată, în momentul executării interogării. Exemplu :

sql>select * from edituri where cod_edit > :coded;

17

Page 18: Lucrare disertatie

Comanda INSERT

Comanda INSERT adaugă un rând într-un tabel existent.

Exemplu:

INSERT INTO Edituri(CodE,Nume,Adresa,Telefon) VALUES(121, 'Albatros','B-dul Tomis Nr. 32 Constanta','0745654765')

Lista de câmpuri de după numele tabelei poate fi omisă dacă toate câmpurile primesc valori, iar acestea sunt scrise în ordinea definită la creare (în care ele apar în capul de tabel). Dacă un câmp nu primeşte valoare el va primi implicit valoarea NULL, dacă la creare, prin modul de declarare a câmpului, introducerea unei astfel de valori este autorizată. Comanda DELETE

Comanda DELETE suprimă una sau mai multe înregistrări dintr-un fişier. Ca şi în cazul comenzii SELECT, pentru definirea unui set de înregistrări care vor fi şterse se utilizează clauza WHERE. Exemplu:

DELETE FROM Autori WHERE CodAut=7DELETE FROM Edituri

Ultima comandă suprimă toate înregistrările din tabelul Edituri. Comanda UPDATE

Comanda UPDATE permite modificarea unei înregistrări sau a unui set de înregistrări. Pentru precizarea setului de înregistrări afectate se foloseste clauza WHERE. Exemplu:

UPDATE Edituri SET Adresa='str. 1 Mai Nr. 12', Telefon='0745343435' WHERE Nume='Dacia'

UPDATE Angajati SET Salar=Salar*1.2 WHERE Salar<450

18

Page 19: Lucrare disertatie

CAPITOLUL 4.

ORACLE JDBC

1. GENERALITĂŢI

Pentru scrierea aplicaţiilor care accesează serverul Oracle XE o soluţie bună este limbajul Java. De altfel firma Oracle Co. pune la dispoziţia utilizatorilor mediul JDeveloper care posedă multiple facilităţi în acest sens. În cele ce urmează se va folosi mediul de programare Netbeans. JDBC (Java DataBase Connectivity) este o colecţie de clase care permite unei aplicaţii client scrisă în Java să acceseze un server de baze de date relaţionale. Folosind aceste clase o aplicaţie poate să se conecteze la serverul de baze de date, poate trimite comenzi SQL şi poate prelucra rezultatele furnizate de server ca urmare a executării acţiunilor comandate. Spre deosebire de ODBC (Open DataBase Connectivity – colecţie de proceduri scrise în C şi dependente de sistemul de operare), colecţia de clase conţinute în JDBC este scrisă în Java fiind astfel realizată independenţa faţă de sistemul de operare. Fişierele sursă care folosesc clase din JDBC trebuie să includă pachetul java.sql. Pentru fiecare server de baze de date există implementări specifice ale JDBC. Astfel în cazul accesării serverului Oracle XE proiectului aplicaţiei client trebuie să i se adauge una dintre arhivele .jar. existente în directorul [ORACLE_HOME]\jdbc\lib. Dacă instalarea serverului Oracle XE s-a făcut în C:, atunci [ORACLE_HOME] este:

1.1. PRINCIPALELE CLASE DIN JDBC Clasa Connection

Pentru a accesa serverul Oracle XE, clasa principală a aplicaţiilor care vor fi realizate va conţine un obiect din clasa Connection. Crearea sa va fi sistematic realizată folosind secvenţa de cod următoare: try { OracleDataSource ods = new OracleDataSource(); ods.setURL("jdbc:oracle:thin:biblio/[email protected]:1521/XE"); cnx = ods.getConnection(); // cnx apartine clasei Connection } catch ( SQLException sqlException ) { System.out.println("Conectare imposibila."); System.exit( 1 ); }

Şirul de caractere subliniat conţine schema (biblio), parola (bibpas), IP-ul serverului pe care rulează Oracle XE (193.226.7.210) şi portul pe care se va realiza conectarea (1521). Înaintea încheierii aplicaţiei este necesară închiderea conexiunii prin apelul metodei close() a acesteia:

cnx.close(); Clasa Statement

Pentru a trimite comenzi SQL individuale serverului de baze de date este necesară crearea unui obiect din clasa Statement. Crearea obiectului se realizează prin apelul metodei createStatement() a clasei Connection :

19

Page 20: Lucrare disertatie

Statement stmt1 = cnx.createStatement() ;sau

Statement stmt2 = cnx.createStatement(tip, acces) ; Dacă va fi folosit pentru trimiterea de comenzi SQL select, obiectul stmt1 va permite crearea unor mulţimi de selecţie care vor putea fi parcurse doar dinspre primul element spre ultimul, nu şi în sens invers. Dacă se doreste crearea ulterioară a unor mulţimi de selecţie care pot fi parcurse în ambele sensuri se va utiliza variant metodei createStatement() cu doi parametri. Primul parametru, tip, va avea una dintre valorile următoare:· ResultSet.TYPE_FORWARD_ONLY, care indică faptul că mulţimea de selecţie creată ulterior va putea fi parcursă doar înainte,· ResultSet.TYPE_SCROLL_INSENSITIVE, care permite realizarea unei mulţimi de selecţie care va putea fi parcursă în ambele sensuri dar nu va reflecta modificările operate de alţi utilizatori pe tabelele folosite la interogare. Al doilea parametru, acces, poate lua valorile:· ResultSet.CONCUR_READ_ONLY semnificând faptul că mulţimile de selecţie care vor fi realizate nu vor putea fi folosite la actualizarea datelor din tabele (nu se vor putea folosi la trimiterea de comenzi update) sau· ResultSet.CONCUR_UPDATABLE care indică faptul că mulţimile de selecţie realizate ulterior folosind stmt2 vor putea servi la actualizarea datelor din tabelele folosite la interogare (corectare, inserare de noi linii). După crearea unui obiect din clasa Statement acesta va putea fi folosit pentru a apela metoda executeQuery() (pentru a trimite serverului comenzi SELECT) sau metoda executeUpdate() (pentru a trimite serverului comenzi CREATE, UPDATE, INSERT sau DELETE). Metoda executeQuery() returnează o mulţime de selecţie în timp ce metoda executeUpdate() returnează un număr întreg reprezentând numărul înregistrărilor afectate de comanda SQL dată. După încheierea folosirii sale, obiectul Statement trebuie suprimat prin apelul metodei close().

stmt.close();

Clasa ResultSet

Un obiect din clasa ResultSet conţine o mulţime de selecţie furnizată de serverul de baze de date ca urmare a executării unei comenzi de interogare (SELECT). Pentru parcurgerea liniilor mulţimii de selecţie un ResultSet integrează un cursor care indică linia curentă a mulţimii. Iniţial, după executarea interogării, cursorul este poziţionat înaintea primei linii. Pentru a avansa pe o nouă linie se foloseste metoda next() . Deoarece metoda next() returnează null la terminarea liniilor mulţimii de selecŃie, aceasta permite scrierea uşoară a unui ciclu de parcurgerea liniilor mulţimii de selecţie.

try {Statement stmt = cnx.createStatement();

ResultSet rs = stmt.executeQuery( "SELECT * FROM Edituri order by nume");while ( rs.next() ) {

System.out.println( rs.getString("nume") );}

stmt.close();} catch (SQLException ex) {}

Un obiect din clasa ResultSet este iniţializat prin executarea metodei executeQuery() a clasei Statement. Dacă crearea s-a făcut ca mai sus, mulţimea de selecţie poate fi parcursă doar înainte, apelând metoda .next(). Dacă mulţimea de selecţie trebuie să fie parcursă în ambele sensuri se va

20

Page 21: Lucrare disertatie

folosi varianta cu parametri a metodei createStatement():Statement stmt =

cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY ) ;

După crearea unei mulţimi de selecţie care poate fi parcursă în ambele sensuri, aceasta va putea fi parcursă folosind metodele:

· first() pentru trecerea pe prima linie,· last() pentru trecere pe ultima linie,

· next() pentru trecere pe următoarea linie sau· previous() pentru trecerea pe linia precedentă

· absolute(nr) pentru plasarea cursorului pe linia nr a mulţimii de selecţie.

Valoarea unui câmp al liniei curente din mulţimea de selecţie se obţine apelând una dintre metodele JDBC get*() din tabelul de mai jos. O metodă get*() poate avea ca argument fie un număr întreg care specifică a câta valoare trebuie extrasă, fie un şir de caractere conţinând numele câmpului. La specificarea numelui câmpului nu contează cu ce caractere este scris - litere mici sau majuscule. La scrierea metodelor get*() având argument numeric se va ţine cont de faptul că numerotarea câmpurilor liniei curente din mulţimea de selecţie începe cu valoarea 1. Dacă tabelul edituri are două câmpuri, Cod_edit si Nume, pentru exemplul dat acelasi rezultat se putea obţine deci scriind :

System.out.println( rs.getString(2) );

O mulţime de selecţie poate servi la actualizarea datelor din tabele folosite la crearea ei. Pentru aceasta obiectul de tip Statement folosit la trimiterea comenzii select trebuie declarat astfel:

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_UPDATABLE);

Corectarea datelor din tabele se realizează ca în exemplul următor:ResultSet rs = stmt.executeQuery("SELECT * FROM Edituri order by nume");

rs.absolute(5); // mută cursorul pe a linia 5 din rsrs.updateString("NUME", "Teora"); // corecteaza câmpul NUME

rs.updateRow(); // se trimite sursei de date linia 5 Pentru inserarea unei noi linii folosind o mulţime de selecţie se va folosi o linie creată în acest scop prin apelul metodei moveToInsertRow(). În această linie pot fi apoi adăugate valorile dorite folosind metode update*() (updateInt(), updateString() etc). Exemplu:

rs.moveToInsertRow(); // mută cursorul pe linia suplimentară creatărs.updateInt(1, "23"); // impune valoarea pt. primul câmp

rs.updateString(2,"Casa cartii"); // idem, câmpul 2

21

Page 22: Lucrare disertatie

rs.insertRow();rs.moveToCurrentRow();

Un ResultSet este închis prin apelul metodei close() sau automat, la închiderea obiectului Statement folosit la crearea sa respectiv la reconstruire (reexecutarea interogării).

Clasa PreparedStatement

Deoarece trimiterea efectivă a unei comenzi SQL folosind un obiect din clasa Statement presupune derularea în prealabil a unui proces de analiză sintactică şi de construire a unei comenzi acceptate de serverul de baze de date, în cazul trimiterii repetate a aceleiasi comenzi SQL se poate câştiga timp dacă procesul de pregătire menţionat se derulează o singură dată pentru tot setul de comenzi. Pentru a realiza acest lucru este necesar însă ca în locul obiectului din clasa Statement să se declare un obiect din clasa înrudită PreparedStatement. Exemplu:

PreparedStatement ps = cnx.prepareStatement("INSERT INTO EdituriVALUES(?,?)");ps.setInt(1, 12);

ps.setString(2, "Minerva");ps.executeUpdate();

ps.setInt(1, 13);ps.setString(2, "Orizonturi");

ps.executeUpdate();ps.setInt(1, 14);

ps.setString(2, "Dacia");ps.executeUpdate();

ps.close; Şirul de caractere care conţine comanda care urmează să fie executată repetat poate conţine caractere '?' care indică poziţiile pe care vor fi inserate valori noi înaintea reapelării metodei executeUpdate() (sau executeQuery(), după caz).

Clasa CallableStatement

Un obiect de tip CallableStatement permite lansarea în execuţie a unei proceduri stocate (scrisă în PL SQL de exemplu). Crearea unui obiect din clasa CallableStatement se realizează ca în exemplele următoare:

a. Procedură stocată fără parametri:CallableStatement cs = cnx.prepareCall("{call procst}");

b. Procedură stocată având 2 parametri:CallableStatement cs = cnx.prepareCall("{call procstoc(?, ?)}");

cs.setString(1,theuser);cs.setString(2,password);

cs.executeQuery();

c. Procedură având doi parametri de intrare, unul de iesire si care returnează o mulţime de selecţie

CallableStatement cs = cnx.prepareCall("{call proc3p(?,?,?)}");cs.setString(1,theuser);

22

Page 23: Lucrare disertatie

cs.setString(2,password);cs.registerOutParameter(3,Types.DATE);

cs.executeQuery();Date dataconect = cs.getDate(3);

CAPITOLUL 5.

REALIZAREA INTERFEŢEI APLICAŢIEI - PARTEA PRACTICĂ

1. Se porneşte mediul de programare (NetBeans 6.7.1 IDE sau o versiune ulterioară) ; 2. Se demarează un nou proiect (File / New Project ... sau se apasă butonul ……

3. Se defineste numele proiectului (Sanatate), se deselectează caseta de validare Create Main Class şi se apasă Finish. Deselectarea casetei Create Main va opri crearea unei clase principale.

23

Page 24: Lucrare disertatie

Aplicaţia care trebuie realizată având interfaţă grafică, este mai simplu să se creeze ulterior o clasă, derivată din clasa Jframe, pe care mediul de programare o va creea ca principală (va conţine main()).

4. Se adaugă proiectului arhiva ojdbc14_g.jar:

24

Page 25: Lucrare disertatie

Paşii realizaţi asigură crearea pe disc a unei structuri de directoare care vor conţine fişierele proiectului. Proiectul nu conţine încă nici o clasă, în arborele acestuia figurând intrarea Source Packages cu o entitate, <default package>.

Crearea ferestrei principale

O aplicaţie care accesează un server de baze de date are caracteristicile unei aplicaţii Windovs obişnuite, respectiv afişează o fereastră principală care conţine o bară cu meniuri derulante, o bară cu instrumente pentru comenzi rapide şi o zonă grafică de afişare.

25

Page 26: Lucrare disertatie

Crearea interfeţei aplicaţiei va începe cu crearea unei clasei principale. În aplicaţiile scrise în Java aceasta poartă numele proiectului şi conţine metoda statică main(). Clasa principală va fi declarată ca derivată din clasa JFrame. O instanţă a clasei principale, creată în cadrul metodei statice main(), va putea atunci servi drept container principal al aplicaţiei (Window frame în figură).

Pentru crearea acestei clase se procedează astfel: - În meniul File se selectează New File :

În fereastra care se afişează se introduce numele noii clase. Fiind clasa principală a aplicaţiei, ea va purta numele proiectului, sanatate. În fereastra New JFrame Form este bine să se indice de asemenea numele unui nou pachet care va înlocui pachetul implicit şi va coţine fişierele sursă ale aplicaţiei.

26

Page 27: Lucrare disertatie

Pentru a da un titlu ferestrei se va selecta un punct din fereastră şi se va modifica proprietatea title. Prin demersuri oarecum asemănătoare vor fi adăugate ferestrele de dialog care vor conţine formularele şi rapoartele necesare exploatării bazei de date Oracle XE. Pentru a impune poziţia în care se va afişa fereastra creată se va selecta fereastra (clic dreapta) şi în meniul contextual se va selecta succesiv Events / Window / windowActivated.

Mediul de dezvoltare va genera metoda formWindowActivated() care va fi modificată astfel:

27

Page 28: Lucrare disertatie

În această etapă se poate testa aplicaţia precum si posibilitatea conectării la serverul Oracle XE. Pentru aceasta se va proceda astfel: - Se inserează la începutul fisierului sanatate.java liniile:import java.sql.*;import oracle.jdbc.*;import oracle.jdbc.pool.OracleDataSource; Aceste linii sunt inserate şi de mediul de programare dacă se include codul care conţine declaraţii ale unor obiecte aparţinând unor clase declarate în aceste pachete: Connection, ResultSet, Statement etc.. După declararea obiectelor se selectează cu butonul drept un punct din fereastra de editare şi în meniul contextual se selectează Fix Imports.

Mediul de programare va afişa o fereastră în care va arăta ce pachete va include. Pentru cazurile în care există mai multe soluţii se va alege varianta din figură.

28

Page 29: Lucrare disertatie

- Se adaugă clasei principale variabila cnx de tip Connection. Pentru aceasta se merge în codul sursă la sfârşit, în zona de declaraţii de variabile şi se tastează declaraţia:

- Se completează constructorului clasei Biblio cu liniile necesare creării obiectului cnx. În prima fază unele linii vor fi evidenţiate ca fiind eronate. Mediul de programare cere ca toate liniile legate de accesarea unei baze de date să fie integrate în secvenţe try - catch.

Mediul poate însă adauga automat secvenţa try - catch corespunzătoare. Pentru aceasta se selectează cu butonul stâng al mouse-ului unul dintre mesajele de eroare şi apoi se selectează Surround Block with try-catch. Rezultat:

public sanatate() {try {OracleDataSource ods = new OracleDataSource();

29

Page 30: Lucrare disertatie

ods.setURL("jdbc:oracle:thin:sanatate/sanatate@localhost:1521/XE");cnx = ods.getConnection();System.out.println("Conectare Ok");initComponents();} catch (SQLException ex) {Logger.getLogger(sanatate.class.getName()).log(Level.SEVERE, null, ex);}} Liniile evidenţiate realizează iniţializarea variabilei cnx. Aceasta va fi folosită în continuare pentru accesul la baza de date. În continuare se poate lansa aplicaţia în execuţie. Dacă nu sunt incidente legate de conectarea la serverul de baze de date, aplicaţia va afişa fereastra principală (goală!), iar în regiunea mediului de programare afectată consolei va apărea şirul de caractere "Conectare Ok".

Realizarea formularelor

Accesul la datele conţinute într-o bază de date se realizează prin formulare şi rapoarte.

Formularele asigură următoarele funcţii principale :· Afişează date individuale;· Permit modificarea datelor afişate;· Permit suprimarea articolelor ;· Permit adăugarea unui articol. Rapoartele prezintă într-un format impus date conţinute în baza de date. În unele cazuri formatul în care datele trebuie prezentate datele este definit prin lege. Aplicaţia trebuie să asigure afişarea pe ecran şi imprimarea rapoartelor. Controale Windows

Formularele prin care sunt accesate datele conţinute într-o bază de date pot fi destinate realizării unei funcţii elementare (afişare date, modificare, adăugare etc.) sau pot realiza o funcţie complexă. Un formular destinat realizării unei funcţii complexe conţine un mare număr de controale Windows, în anumite stări ale aplicaţiei putându-se pune chiar problema ascunderii unora dintre ele. O aplicaţie care conţine formulare simple, fiecare destinat realizării unei acţiuni elementare, poate pune probleme de operare, dar practica programării recomandă această abordare deoarece atât depanarea cât şi întreţinerea aplicaţiilor astfel concepute este mai simplă.

JMenuBar

Iniţierea diferitelor acţiuni se realizează în principal folosind meniuri derulante şi butoane. Meniurile derulante vor declanşa principalele funcţii ale aplicaţiei (afişarea formularelor şi rapoartelor, salvarea bazei de date, oprirea aplicaţiei), iar butoanele vor declansa acţiuni în interiorul formularelor. Pentru a defini meniul unei aplicaţii trebuie creată o bară de meniuri (obiect aparţinând clasei JMenuBar), un ansamblu de meniuri derulante (obiecte de tip JMenu) şipentru fiecare meniu derulant, un ansamblu de opţiuni (obiecte aparţinând clasei JMenuItem). Pentru a realiza o aplicaţie care accesează baza de date Oracle XE, schema Sanatate, se va proceda astfel:

a. Se adaugă proiectului bara cu meniuri derulante:

30

Page 31: Lucrare disertatie

Se va selecta cu mouse-ul Menu Bar şi se va realiza adăugarea sa printr-un clic cu mouse-ul în fereastra aplicaţiei.

În continuare se va edita conţinutul barei cu meniuri folosind reprezentarea arborescentă afişată prin selectarea tabului Inspector.

b. Se modifică numele primului meniu derulant (proprietatea text):

c. Se adaugă meniului Operaţii opţiunea Iesire. Efectul selectării acesteia va fi oprirea aplicaţiei. Pentru a iniţia adăugarea noii opţiuni se selectează cu butonul drept al mouse-ului meniul Operaţii şi apoi se selectează în meniul contextual Add From Palette / Menu Item.

31

Page 32: Lucrare disertatie

Rezultat:

Se modifică apoi proprietatea text a opţiunii nou adăugate în Iesire:

d. Se editează apoi al doilea meniu de pe bara cu meniuri derulante. Se modifică proprietatea text a noului obiect din Edit în Formulare:

32

Page 33: Lucrare disertatie

Celui de-al doilea meniu derulant i se vor adăuga în timp mai multe intrări, fiecare având rolul de a declanşa afişarea unuia dintre formularele care vor fi realizate. În acelaşi mod va fi adăugat aplicaţiei un al treilea meniul derulant, Rapoarte, ale cărui intrări vor fi folosite pentru a declansa afişarea rapoartelor. Pentru a creea metoda care trebuie executată la selectarea unei opţiuni dintr-un meniu derulant se va selecta opţiunea cu un dublu clic în fereastra Inspector sau se va selecta opţiunea în fereastra Design cu butonul drept al mouse-ului şi în meniul contextual se va selecta Events / Action / actionPerformed.

Pentru opţiunea Iesire din primul meniu derulant funcţia astfel adăugată trebuie completată cu secvenţa de cod care închide conexiunea cu serverul şi apoi apelează metoda System.exit(0) a cărui efect este oprirea imediată a aplicaţiei.

private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt){

try {// TODO add your handling code here:

cnx.close();} catch (SQLException ex) {

Logger.getLogger(sanatate.class.getName()).log(Level.SEVERE,null, ex);}

System.exit(0);}

Secvenţa try-catch a fost adăugată de mediul de programare. Practic s-a scris cnx.close(); după care s-a selectat cu mouse-ul simbolul care indica o eroare şi s-a selectat opţiunea Surround Statement with try-catch.

33

Page 34: Lucrare disertatie

JLabel

Controlul de tip JLabel serveşte la plasarea într-un formular a unui text sau a unei imagini. După includerea controlului trebuie setate principalele proprietăţi ale acestuia, respectiv text sau icon pentru definirea conţinutului, font, foreground, background s.a.

Proprietãţile icon şi text se pot folosi împreunã. Dacã se selecteazã icon trebuie indicat fişierul care conţine imaginea de afişat, aceasta fiind în format JPEG (Joint Photographic Experts Group, având extensia .jpg) sau GIF (Graphics Interchange Format având extensia .gif).

34

Page 35: Lucrare disertatie

JTextField

Controlul de tip JTextField, este folosit la afişarea sau introducerea şirurilor de caractere.Accesul la conţinutul unui control de tip JTextField se realizează cu perechea de metode setText() (impunere String conţinut) şi getText() (preluare String conţinut) ca în exemplul următor:

nume_spital.setText(nm);. . .

String nume = nume_spital.getText(); Exemplu : Să se adauge aplicaţiei un formular care permite navigarea în tabelul Spitale. Pentru navigare se vor folosi două butoane având pentru proprietatea text valoarea Inainte respectiv Inapoi. Rezolvare: În NetBeans soluţia rapidă pentru adăugarea unei ferestre de dialog constă în selectarea succesivă cu mouse-ul a butonului JDialog din fereastra Palette şi a ferestrei principale (sau, mai general, fereastra aplicaţiei în cadrul căreia se va afişa noua fereatră). După adăugarea ferestrei de dialog se începe configurarea acesteia. Prima operaţie va fi schimbarea numelui implicit din jDialog1 în spitale. Pentru aceasta se selectează cu butonul drept al mouse-ului în fereastra Inspector noua fereastră si apoi, în meniul contextual, se selectează Change Variable Name...

35

Page 36: Lucrare disertatie

Pentru a edita conţinutul ferestrei de dialog se selectează cu un dublu clic în fereastra Inspector identificatorul acesteia:

Ca şi în cazul ferestrei principale, pentru a impune un titlu care se va afişa pe bara ferestrei se selectează cu mouse-ul un punct din fereastră şi se scrie titlul dorit în dreptul proprietăţii Title. Folosind instrumentele din fereastra Palette, se adaugă noii ferestre cinci controale Windows: o etichetă (JLabel având text=Nume), o casetă de text (JTextBox având Name=numespit) şi trei butoane având numele spitprec, spiturm respectiv ies şi proprietăţile text ca în figura următoare:

Pentru a modifica etichetele butoanelor se accesează proprietatea text a acestora sau se selectează controlul cu butonul stâng al mouse-ului şi se selectează Edit Text în meniul contextual.

Înainte de a continua cu scrierea secvenţelor de cod necesare funcţionării noii ferestre se va verifica în fereastra Inspector corecitudinea configurării.

36

dublu clic

Page 37: Lucrare disertatie

Deoarece rolul acestui formular este parcurgerea tabelului Spitale, clasei principale i se va adăuga un obiect din clasa ResultSet denumit rez. Acesta va fi iniţializat într-o secvenţă de cod executată la deschiderea formularului şi va fi închis (se va apela metoda close()) la închiderea acestuia. De asemenea se va adăuga clasei principale obiectul comanda aparţinând clasei Statement. Acesta va permite crearea obiectului rez care va conţine mulţimea de selecţie rezultată în urma executării de către serverul Oracle XE a comenzii SQL de selectare a editurilor din baza de date. Zona din codul clasei destinată declaraţiei variabilelor clasei va conţine deci variabilele următoare:

private Connection cnx;private Statement rez;

private ResultSet comanda; Pentru a realiza acţiuni înaintea afişării unei ferestre (JFrame sau JDialog) este necesară adăugarea unei metode asociate evenimentului windowActivated . Pentru aceasta se va selecta cu butonul drept al mouse-ului un punct din fereastră în care nu există nici un control Windows şi în meniul contextual se va selecta Events / Window / windowActivated.

37

Page 38: Lucrare disertatie

În cazul formularului spitale, metoda spitaleWindowActivated() astfel adăugată va iniţializa succesiv variabilele comanda (Statement) şi rez (ResultSet) şi va plasa în controlul numespit numele primului spital.private void SpitaleWindowActivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try { comanda = cnx.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); rez = comanda.executeQuery("SELECT * FROM spitale"); if (rez.next()) { String nm = rez.getString("nume"); numespit.setText(nm); } } catch (SQLException sqlException) { System.out.println("Conectare imposibila."); System.exit(1); }}

Practic s-a adăugat doar codul evidenţiat, adăugarea instrucţiunii try-catch realizându-se de mediul de programare, ca în exemplele precedente. La închiderea ferestrei este necesară apelarea metodelor close() pentru obiectele rez şi comanda. Pentru a adăuga aplicaţiei o metodă care se apelează la închiderea formularului spitale se procedează ca mai sus, evenimentul selectat fiindwindowDeactivated.

private void SpitaleWindowDeactivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try { rez.close(); comanda.close();

38

Page 39: Lucrare disertatie

} catch (SQLException ex) { ex.printStackTrace(); } }

Pentru a iniţia introducerea secvenţei de cod care trebuie executată la acţionarea unui buton se modifică proprietatea actionPerformed sau, mai simplu, se selectează controlul cu un dublu clic. Mediul de dezvoltare va include automat o funcţie de tratare a evenimentului al cărui conţinut trebuie apoi editat.

private void spiturmActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: try { if (!rez.isLast()) // nu este pe ultima linie { spitprec.setEnabled(true); if (rez.next()) // Trec pe urmatoarea linie { // preiau numele String nm = rez.getString("nume"); numespit.setText(nm); } } else { spiturm.setEnabled(false); } } catch (SQLException esq) { } }

La fel se iniţiază scrierea codului pentru celelalte două butoane, spitprec şi ies: private void spiturmActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: try { if (!rez.isLast()) // nu este pe ultima linie { spitprec.setEnabled(true); if (rez.next()) // Trec pe urmatoarea linie { // preiau numele String nm = rez.getString("nume");

39

Page 40: Lucrare disertatie

numespit.setText(nm); } } else { spiturm.setEnabled(false); } } catch (SQLException esq) { } }

private void iesActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: Spitale.setVisible(false);

Metoda setVisible(false) realizează ascunderea ferestrei de dialog. Pentru a realiza afişarea ferestrei de dialog create se revine la fereastra principală (dublu clic pe JFrame în fereastra Inspector) şi se adăugă meniului Formulare o primă opţiune, Spitale. În continuare se modifică proprietatea text a noii opţiuni în Spitale. Se crează metoda care trebuie executată la selectarea noii opţiuni. Pentru aceasta se selectează opţiunea cu butonul drept al mouse-ului şi în meniul contextual afişat se selectează Events / Action / Action Performed. Conţinutul metodei pspitaleActionPerformed() este următorul:

private void pspitaleActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: Spitale.setLocation(120, 170); Spitale.setVisible(true); Spitale.pack();

Codul cuprinde o linie care impune poziţia noii ferestre spitale.setLocation()), determină afişarea ferestrei (spitale.setVisible(true)) şi impune reconstruirea interfeţei conţinute (spitale.pack()) în acord cu managerul de dispunere a obiectelor grafice (eng. layout manager).

În continuare se poate executa aplicaţia.

40

Page 41: Lucrare disertatie

Se crează un formular pentru adăugarea cititorilor în baza de date, astfel:

Crearea în baza de date sanatate, un nou tabel, judet, cu 3 câmpuri, cod_jud (number(2,0)), judet

(varchar2(50)) şi acronim (char(2) şi introducerea câtorva judeţe.

Se adăugă proiectului sanatate o altă intrare în submeniul Formulare/ Adăugare – Pacienti.(JMenuItem).

Se adăugă intrării apacienti ( = adăugare pacienti) evenimentului actionPerformed codul: APacient.setLocation(120, 170); APacient.setVisible(true); APacient.pack();Se adăugă clasei principale două noi obiecte, unul adpacrez, din clasa Statement ( iniţializat ladeschiderea formularului şi închis la ieşirea din acesta), şi un al doilea, interogare1, din clasaResultSet (acesta va conţine comenzi SQL individuale care vor fi apoi trimise serverului OracleXE ).Se ataşează evenimentului windowActivated ( în fereastra Inspector : Form Sanatate ->Other Components -> APacienti) metoda APacientWindowActivated care va conţine:

41

Page 42: Lucrare disertatie

- iniţializarea celor două obiecte (adpacrez şi interogare1);- popularea cu date a listei controlului jud de tip combobox; try { adpacrez = cnx.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); interogare1 = adpacrez.executeQuery("SELECT * FROM judet order by judet"); jud.removeAllItems(); while (interogare1.next()) { String nm = interogare1.getString("judet"); jud.addItem(nm); } } catch (SQLException ex) { ex.printStackTrace(); System.exit(1); } } Se ataşează evenimentului windowDeactivated metoda APacientWindowDeactivated try { adpacrez.close(); interogare1.close(); } catch (SQLException ex) { ex.printStackTrace(); } }codul necesar preluării conţinuturilor din controale şi apoi scrierii în baza de date este : try { String cenepe, nume, prenume, localitatea, adresa, telefon, profesia; int jude; cenepe = cnp.getText(); nume = numpac.getText(); prenume = prenpac.getText(); localitatea = loc.getText(); int poz = jud.getSelectedIndex(); // Poz. in lista interogare1.absolute(poz + 1); // mut cursorul pe linia poz+1 jude = interogare1.getInt("cod_jud"); adresa = adr.getText(); telefon = tel.getText(); profesia = prof.getText(); String frazaSQL = "INSERT into pacienti VALUES (autopac.NEXTVAL"; frazaSQL += "," + apostrof(cenepe); frazaSQL += "," + apostrof(nume); frazaSQL += "," + apostrof(prenume); frazaSQL += "," + apostrof(localitatea); frazaSQL += "," + jude; frazaSQL += "," + apostrof(adresa); frazaSQL += "," + apostrof(telefon); frazaSQL += "," + apostrof(profesia) + ")";// Creez un Statement*/ Statement stm = cnx.createStatement();

42

Page 43: Lucrare disertatie

// Apelez metoda executeUpdate() pt. a trimite comanda INSERT System.out.println(frazaSQL); stm.executeUpdate(frazaSQL); stm.close(); } catch (SQLException ex) { ex.printStackTrace(); cnp.setText(""); numpac.setText(""); prenpac.setText(""); loc.setText(""); adr.setText(""); tel.setText(""); prof.setText(""); } }Se adăugă codul necesar închiderii formularului APacienti APacient.setVisible(false);Se rulează aplicatia

Crearea unui formular pentru vizualizarea bolilor existente într-o sectie, astfel:

Se adăugă proiectului sanatate o altă intrare în meniul Formulare, Situatii – de tip JMenu, cu o

43

Page 44: Lucrare disertatie

intrare de tip JMenuItem, Boli şi secţii.

Se adăugă pentru intrarea bolisec ( = bolile dintr-o secţie) metoda de tratare a evenimentuluiactionPerformed care va conţine codul: Bolisec.setLocation(120, 170); Bolisec.setVisible(true); Bolisec.pack();Se adăugă clasei principale două variabile globale, sectii_comanda şi sectii_rs de tip Statementrespectiv ResultSet. Aceste două variabile vor fi folosite pentru a popula controlul sectiaa(JcomboBox): private Statement sectii_comanda; private ResultSet sectii_rs;Se adăugă clasei principale încă o variabilă, dateTabel din clasa ArrayList. Această variabilă va conţine informaţiile din liniile tabelului bolsec. private ArrayList dateTabel;Se populează controlul JComboBox cu secţiile din baza de date: try {sectii_comanda= cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);sectii_rs= sectii_comanda.executeQuery("SELECT * from sectii"); sectiaa.removeAllItems();while (sectii_rs.next()) {String n = sectii_rs.getString("nume");aut.addItem(n);}// Preiau codul primei sectii din lista sectii_rs.first();int codse = sectii_rs.getInt("cod_sectia"); } catch (SQLException ex) {Logger.getLogger(sanatate.class.getName()).log(Level.SEVERE, null, ex); }Se preiau numele secţiilor al căror cod este în codse şi se adăugă în dateTabel: boala_stmt = null; rs = null; boala_stmt = cnx.createStatement(); rs = boala_stmt.executeQuery("SELECT boli.nume, sectii.nr_paturi FROM sectii, boli, bolsec WHERE boli.cod_boala = bolsec.cod_boala and sectii.cod_sectia = bolsec.cod_sectia and boli.cod_boala = " + String.valueOf(codse)); dateTabel = new ArrayList();// Copiez liniile din rs in dateTabel while (rs.next()) { ArrayList linie = new ArrayList(); String boli = rs.getString("nume"); int nr_paturi = rs.getInt("nr_paturi");

44

Page 45: Lucrare disertatie

linie.add(boli); linie.add(nr_paturi); dateTabel.add(linie); } boala_stmt.close();Se crează obiectul necesar păstrării datelor controlului bolisec (JTable). Pentru aceasta seconstruieşte o clasă abstractă derivată din AbstractTableModel: secboli.setModel(new AbstractTableModel() { private String[] colNume = {"Boli", "Nr. paturi"}; public int getRowCount() { return dateTabel.size(); } public int getColumnCount() { return colNume.length; } public Object getValueAt(int linie, int col) {// Preiau linia rowIndex ArrayList rand_cautat = (ArrayList) dateTabel.get(linie); return rand_cautat.get(col); } @Override public String getColumnName(int column) { return colNume[column]; } });// Redimensionez prima coloana TableColumn column = null; column = secboli.getColumnModel().getColumn(0); column.setPreferredWidth(300);la închiderea formularului trebuie apelată metoda close pentru obiectul de tip Statementfolosit: private void BolisecWindowDeactivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try { sectii_comanda.close(); } catch (SQLException ex) { ex.printStackTrace(); } }Se ataşează o metodă de tratare a evenimentului produs la selectarea unui nou autor în controlul sectiaa (JComboBox) . În această metodă se va prelua codul autorului selectat de utilizator şi se va repopula controlul secboli (JTable).private void sectiaaActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: // Se selecteaza codul bolii int linia = sectiaa.getSelectedIndex(); if (linia >= 0) { try { sectii_rs.absolute(linia + 1); int codse = sectii_rs.getInt("Cod_sectia");

45

Page 46: Lucrare disertatie

// Repopulez tabelul . . . boala_stmt = null; rs = null; boala_stmt = cnx.createStatement(); rs = boala_stmt.executeQuery("SELECT boli.nume, sectii.nr_paturi FROM sectii, boli, bolsec WHERE sectii.cod_sectia = bolsec.cod_sectia and boli.cod_boala = bolsec.cod_boala and sectii.cod_sectia = "+String.valueOf(codse)); dateTabel = new ArrayList();// Copiez liniile din rs in dateTabel while (rs.next()) { ArrayList linie = new ArrayList(); String secti = rs.getString("nume"); int nr_paturi = rs.getInt("nr_paturi"); linie.add(secti); linie.add(nr_paturi); dateTabel.add(linie); } boala_stmt.close(); secboli.setModel(new AbstractTableModel() { private String[] colNume = {"Boli", "Nr. paturi"}; public int getRowCount() { return dateTabel.size(); } public int getColumnCount() { return colNume.length; } public Object getValueAt(int linie, int col) {// Preiau linia rowIndex ArrayList rand_cautat = (ArrayList) dateTabel.get(linie); return rand_cautat.get(col); } @Override public String getColumnName(int column) { return colNume[column]; } });// Redimensionez prima coloana TableColumn column = null; column = secboli.getColumnModel().getColumn(0); column.setPreferredWidth(300); } catch (SQLException ex) { Logger.getLogger(sanatate.class.getName()).log(Level.SEVERE, null, ex); } } }Metoda executată la apăsarea butonului "Iesire" private void ies3ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: Bolisec.setVisible(false);Rulare

46

Page 47: Lucrare disertatie

Crearea unui formular pentru parcurgerea spitalelor din baza de date, astfel:

Se adăugă clasei principale două noi obiecte, unul din clasa Statement, nume_spital si celălaltdin clasa ResultSet, interogare_spitale.private Statement nume_spital ;private ResultSet interogare_spitale ;Se adăugă în evenimentul windowActivated try { nume_spital = cnx.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); interogare_spitale = nume_spital.executeQuery("SELECT * FROM spitale order by nume"); nume_spit.removeAllItems(); while (interogare_spitale.next()) { String nm = interogare_spitale.getString("nume"); nume_spit.addItem(nm); }

47

Page 48: Lucrare disertatie

} catch (SQLException ex) { ex.printStackTrace(); System.exit(1); } Se adăugă în evenimentul ActionPerformed ataşat controlului JComboBox:

try { // Se selecteaza codul spitalului int linia = nume_spit.getSelectedIndex();//caut linia spitalului selectat

if (linia >= 0) { interogare_spitale.absolute(linia + 1); // mut cursorul in interogare-spital pe linie codspit = interogare_spitale.getInt("cod_spital"); //preiau spitalul selectat intr-o variabila //populez textboxurile try { comanda = cnx.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); rez = comanda.executeQuery("SELECT adresa, telefon FROM spitale WHERE

cod_spital ="+codspit); if (rez.next()) { String sir1 = rez.getString("adresa"); String sir2 = rez.getString("telefon"); adresa_spit.setText(sir1); telefon_spit.setText(sir2); } } catch (SQLException ex) { ex.printStackTrace(); } } } catch (SQLException ex) { ex.printStackTrace(); }

Crearea unui formular pentru adaugarea unei noi secţii

Se adăugă proiectului sanatate o altă intrare în submeniul Adaugare, Sectie – de tip JMenuItem:

48

Page 49: Lucrare disertatie

Se crează un formular pentru introducerea secţiilor noi în baza de date, astfel:

Se adăugă intrării asectie ( = adaugare secţii) evenimentului actionPerformed codul: ASectie.setLocation(120, 170); ASectie.setVisible(true); ASectie.pack();

Se declară 4 variabile globale , două de tip Statement şi două de tip ResultSet:private Statement diagnostice;

private ResultSet rezultat_diagnostice;

private Statement spitalele;private ResultSet rezultat_spitalele;

la deschiderea formularului trebuie rulat codul pentru popularea celor două controale de tipJComboBox, unul pentru lista diagnosticelor şi celălalt pentru lista spitalelor din baza de date:private void ASectieWindowActivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try {//populez lista diagnosticelor diagnostice= cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rezultat_diagnostice = diagnostice.executeQuery("SELECT * from boli order by nume"); diagnostic.removeAllItems(); while (rezultat_diagnostice.next()) { String n = rezultat_diagnostice.getString("nume");

49

Page 50: Lucrare disertatie

diagnostic.addItem(n); }//populez lista spitalelor spitalele = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rezultat_spitalele = spitalele.executeQuery("SELECT * from spitale"); spital.removeAllItems(); while (rezultat_spitalele.next()) { String n = rezultat_spitalele.getString("nume"); spital.addItem(n); } } catch (SQLException ex) { ex.printStackTrace(); } }la închiderea formularului se ruleazăprivate void ASectieWindowDeactivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try { diagnostice.close(); spitalele.close(); } catch (SQLException ex) { ex.printStackTrace(); } }Se declară două variabile globale, codboli şi codspit pentru preluarea codurilor bolii şi spitalului selectate;Se preia din controlul de tip JComboBox diagnostic, codul autorului selectat de utilizator, astfel:try {// Se selecteaza codul bolii int linie = diagnostic.getSelectedIndex(); if (linie >= 0) { rezultat_diagnostice.absolute(linie + 1); codboli = rezultat_diagnostice.getInt("Cod_boala"); } } catch (SQLException ex) { ex.printStackTrace(); }Se preia din controlul de tip JComboBox cu numele spital, codul editurii selectate deutilizator, astfel:try {// Se selecteaza codul editurii int linie = spital.getSelectedIndex(); if (linie >= 0) { rezultat_spitalele.absolute(linie + 1); codspit = rezultat_spitalele.getInt("cod_spital"); } } catch (SQLException ex) { ex.printStackTrace(); }la apăsarea butonului "Iesire":

ASectie.setVisible(false);la apăsarea butonului "Adaugare": try {

50

Page 51: Lucrare disertatie

String num, nr; num = numele.getText(); nr = paturi.getText(); String frazaSQL = "INSERT into sectii VALUES (autosec.NEXTVAL"; frazaSQL += "," + apostrof(num) + "," + codspit + "," + apostrof(nr) + ")";// Creez un Statement*/ Statement stm = cnx.createStatement();// Apelez metoda executeUpdate() pt. a trimite comanda INSERT System.out.println(frazaSQL); stm.executeUpdate(frazaSQL);//preiau codul sectiei introduse int c; s = cnx.createStatement(); r = s.executeQuery("SELECT autosec.CURRVAL as c from dual"); r.next(); c = r.getInt("c");//adaug sectia si in bolsec String fraza1SQL = "INSERT into bolsec VALUES (" + codboli + "," + c + ")"; System.out.println(fraza1SQL); stm.executeUpdate(fraza1SQL); stm.close();//golesc campurile numele.setText(""); paturi.setText(""); } catch (SQLException ex) { ex.printStackTrace(); }la apăsarea butonului "Alt diagnostic":

ABoli.setLocation(120, 170);ABoli.setVisible(true);

ABoli.pack();

la apăsarea butonului "Alt spital":ASpital.setLocation(120, 170);

ASpital.setVisible(true);ASpital.pack();

Crearea unui formular pentru inregistrarea internărilor

Se adăugă proiectului sanatate o altă intrare în submeniul Operatii, Miscare pacienti – de tip JMenuItem:

51

Page 52: Lucrare disertatie

Se crează un formular pentru introducerea datelor pacientilor internati în baza de date, astfel:

Se adăugă intrării miscarepac ( = adaugare secţii) evenimentului actionPerformed codul: MPacienti.setLocation(120, 170); MPacienti.setVisible(true); MPacienti.pack();

la deschiderea formularului trebuie rulat codul pentru popularea celor patru controale de tipJComboBox, pentru lista pacientilor, pentru lista diagnosticelor, pentru lista sectiilor si pentru cea a spitalelor din baza de date:private void MPacientiWindowActivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here:try {//populez lista pacientilor pacientii = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

52

Page 53: Lucrare disertatie

rezultat_pacientii = pacientii.executeQuery("SELECT * from pacienti order by nume"); numepacient.removeAllItems(); while (rezultat_pacientii.next()) { String n = rezultat_pacientii.getString("nume")+ rezultat_pacientii.getString("prenume"); numepacient.addItem(n); }//populez lista sectiei sectiile = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rezultat_sectiile = sectiile.executeQuery("SELECT * from sectii order by nume"); sectia.removeAllItems(); while (rezultat_sectiile.next()) { String n = rezultat_sectiile.getString("nume"); sectia.addItem(n); } //populez lista diagnosticului diagnostice = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rezultat_diagnostice = diagnostice.executeQuery("SELECT * from boli order by nume"); diagnosticul.removeAllItems(); while (rezultat_diagnostice.next()) { String n = rezultat_diagnostice.getString("nume"); diagnosticul.addItem(n); }//populez lista spitalelor spitalele = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rezultat_spitalele = spitalele.executeQuery("SELECT * from spitale order by nume"); spitalul.removeAllItems(); while (rezultat_spitalele.next()) { String n = rezultat_spitalele.getString("nume"); spitalul.addItem(n); } } catch (SQLException ex) { ex.printStackTrace(); }

la apăsarea butonului "Inregistrare": private void inregistrActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: try { String dataint, dataext; int paci, dgn, sect, spi; dataint = dataintern.getText(); //System.out.println(dataint); dataext = dataextern.getText(); int poz = numepacient.getSelectedIndex(); int poz1 = diagnosticul.getSelectedIndex();

53

Page 54: Lucrare disertatie

int poz2 = sectia.getSelectedIndex(); int poz3 = spitalul.getSelectedIndex(); rezultat_pacientii.absolute(poz + 1); // mut cursorul pe linia poz+1 paci = rezultat_pacientii.getInt("cod_pac"); // System.out.println(paci); rezultat_diagnostice.absolute(poz1 + 1); // mut cursorul pe linia poz1+1 dgn = rezultat_diagnostice.getInt("cod_boala"); rezultat_sectiile.absolute(poz2 + 1); // mut cursorul pe linia poz2+1 sect = rezultat_sectiile.getInt("cod_sectia"); rezultat_spitalele.absolute(poz3 + 1); // mut cursorul pe linia poz3+1 spi = rezultat_spitalele.getInt("cod_spital"); String frazaSQL = "INSERT into internari VALUES (" + paci + "," + sect + "," + dgn + "," + spi + "," + apostrof(dataint) + "," + apostrof(dataext) + ")";// Creez un Statement*/ Statement stm = cnx.createStatement();// Apelez metoda executeUpdate() pt. a trimite comanda INSERT System.out.println(frazaSQL); stm.executeUpdate(frazaSQL); stm.close(); } catch (SQLException ex) { ex.printStackTrace(); dataintern.setText(""); dataextern.setText(""); }

la apăsarea butonului "Iesire":MPacienti.setVisible(false);

Crearea de rapoarte

Raport simplu

54

Page 55: Lucrare disertatie

la apăsarea butonului "Vezi":private void VizualizareActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: String raport = "./rapoarte/spitale.jrxml"; // Fisier realizat de iReports HashMap params = new HashMap(); try { JasperReport jasperReport = JasperCompileManager.compileReport(raport); JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, cnx); JasperViewer.viewReport(jasperPrint, false);

}catch (JRException ex) { ex.printStackTrace();}la apăsarea butonului "Out":private void IesireActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: ListaSpit.setVisible(false);

Raport cu grad de dificultate mai ridicat

55

Page 56: Lucrare disertatie

la deschiderea formularului trebuie rulat codul pentru popularea controlului de tipJComboBox :private void ListaPacWindowActivated(java.awt.event.WindowEvent evt) { // TODO add your handling code here: try { jud_comanda = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); jud_rs = jud_comanda.executeQuery("SELECT * from judet order by judet"); judet.removeAllItems(); while (jud_rs.next()) { String n = jud_rs.getString("judet"); judet.addItem(n); } } catch (SQLException ex) { ex.printStackTrace(); }

Se preia din controlul de tip JComboBox cu numele judet, codul judetului selectat deutilizator, astfel:private void judetActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: try {// Se selecteaza codul judetului int linie = judet.getSelectedIndex();

56

Page 57: Lucrare disertatie

if(linie >= 0) { jud_rs.absolute(linie + 1); codjud = jud_rs.getInt("cod_jud");// codjud este variabilă de tip int, a clasei numejud = jud_rs.getString("judet"); //numejud este variabilă de tip String, a clasei System.out.println(codjud); } } catch (SQLException ex) { ex.printStackTrace(); }

la apăsarea butonului "Vizualizare":private void vizActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: String raport = "./rapoarte/pacientiipejud.jrxml"; // Fisier realizat de iReports HashMap params = new HashMap(); // se definesc valoarea parametrului din raport, codjud // System.out.println("Codjud="+codjud); params.put("codjud", codjud); params.put("numejud", numejud); // Se poate face raportul try { JasperReport jasperReport = JasperCompileManager.compileReport(raport); JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, cnx); JasperViewer.viewReport(jasperPrint, false);

}catch (JRException ex) { ex.printStackTrace();}

la apăsarea butonului "Iesire": ListaPac.setVisible(false);

Relaţii între tabelele din baza de date

57

Page 58: Lucrare disertatie

58

Page 59: Lucrare disertatie

BIBLIOGRAFIE

1. [CONN00] T.Connolly – “Database Systems”, ed.Mc Graw Hill, 2000.

2. [DATE94] J.Date – “ An introduction to Database Systems”, ed. Addison Wesley, 1994

3. [FOTA01] M. Fotache – “SQL. Dialecte DB2, Oracle, Visual FoxPro”, ed. Polirom, 2001

4. [LUBO95] I. Lungu, C. Bodea ş. a. - “Baze de date – organizare, proiectare şi implementare “, ed. ALL, 1995.

5. [LUIA05] I. Lungu, I. Iacob – “Aplicaţii informatice utilizând SGBD Oracle”, ed.

ProUniversalis, 2005

6. [LUIO02] I. Lungu, M. Iorga, M Velicanu – “Baze de date. Să învăţăm sistemul Oracle în 28 de lecţii.”, ed. Economică, 2002

7. [LURO93] I.Lungu, I. Roşca, N. Muşat, Gh. Sabău – “Baze de date relaţionale. Utilizarea limbajului SQL*PLUS”, ed. ALL, 1993

8. [LUVE00] M.Velicanu, I.Lungu, M.Muntean – “Teste şi probleme de programare în Visual Foxpro şi Oracle”, ed.Petrion, 2000.

9. [VELU00] M.Velicanu, I.Lungu ş.a. – “Sisteme de gestiune a bazelor de date”, ed.Petrion, 2000.

10. [VELU01] M.Velicanu, I.Lungu, M.Muntean – “Dezvoltarea aplicaţiilor cu baze de date în Visual Foxpro”, ed. ALL, 2001

11. [VELU02] M.Velicanu, I.Lungu, M.Muntean, M.Iorga, S.Ionescu – “Oracle – platformă pentru baze de date”, ed. Petrion, 2002.

12. [VELU03] M.Velicanu, I.Lungu, M.Muntean, S. Ionescu – “Sisteme de baze de date”,

ed.Petrion, 2003. 13. www.oracle.com

14. www.oracle-base.com

59

Page 60: Lucrare disertatie

CUPRINS

CAPITOLUL 1. TEORIA BAZELOR DE DATE RELAŢIONALE…………………………………………………2 MODELUL RELAŢIONAL…………………………………………………………………………………..……..2 BAZE DE DATE RELAŢIONALE……………………………………………………………………………..…..3 EXEMPLE DE SISTEME DE GESTIUNE A BAZELOR DE DATE RELAŢIONALE………………..……...4 CAPITOLUL 2. FACILITĂŢILE ŞI ARHITECTURA SISTEMULUI ORACLE…………………..……………..5 EVOLUŢIA ŞI FACILITĂŢILE SISTEMULUI ORACLE……………………..…………………………….....5 ARHITECTURA SISTEMULUI ORACLE………………………………………………………………………...6 ORACLE SERVER…………………………………………………………………………………………………...6

CAPITOLUL 3. ELEMENTELE DE BAZĂ ALE LIMBAJULUI SQL…………………………………………….8 INTRODUCEREA COMENZILOR SQL FOLOSIND INTERFAŢA GRAFICĂ………………………….….8 TIPURI DE DATE SUPORTATE DE ORACLE…………………………………………………………….…...10 CREAREA TABELELOR ÎN ORACLE XE……………………………………………………………………..11

CAPITOLUL 4. ORACLE JDBC…………………………………………………….………………………………..19 GENERALITĂŢI……………………………………………………………………………………………………19 PRINCIPALELE CLASE DIN JDBC……………………………………………………………………...………19

CAPITOLUL 5.REALIZAREA INTERFEŢEI APLICAŢIEI - PARTEA PRACTICĂ………………..……….23

BIBLIOGRAFIE .............................................................................................................................................................59

60