Transcript
Page 1: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

Universitatea Politehnica Bucureşti

Facultatea de Automatică şi Calculatoare

Departamentul de Automatică şi Ingineria Sistemelor

LUCRARE DE LICENŢĂ

Sistem Object Relational Mapping in Java

Bucureşti,2013

Coordonator Şl. Dr. Ing. Ştefan Ioan Sacală

Absolvent George-Alin Dragomir

Page 2: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

CUPRINS

Abstract 4

Notaţii şi Abrevieri 5

Listă de figuri 6

Listă de secvenţe de cod 7

1. Introducere 8

1.1 Contextul 8

1.2 ORM (Object Relational Mapping) 9

1.3 Motivatia dezvoltării unui sistem ORM 10

1.4 Descrierea proiectului 11

2. Alegerea Platformei 12

3. Tehnologii folosite 13

3.1 IDE(Mediu integrat de dezvoltare) 13

3.2 Sisteme de management ale bazelor de date relaţionale 16

3.2.1 PostgreSQL 16

3.2.2 Microsoft Sql Server 16

3.3 API-uri folosite 17

3.3.1 API-ul de JDBC(Java Database Connectivity) 17

3.3.2 API-ul de Reflection 18

3.3.3 API-ul de SWT(Standard Widget Toolkit) 19

3.3.4 API-ul pentru crearea de fişiere PDF 21

4. Dezvoltarea aplicaţiei 22

4.1 Cerinţele aplicaţiei 22

4.2 Arhitectura 23

Page 3: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

4.3 Structura proiectului 24

4.4. Funcţionalităţile sistemului şi tratarea problemelor 27

5. Testarea aplicaţiei 38

5.1 Fereastra principală 38

5.2 Fereastra Medic 39

5.3 Fereastra Farmacist 43

5.4 Fereastra Pacient 44

6. Concluzii şi Dezvoltări ulterioare 47

6.1 Dezvoltări ulterioare 47

6.2 Concluzii 47

7. Bibliografie 48

ANEXĂ COD 50

Page 4: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

Abstract

Proiectul îşi propune a fi o aplicaţie de dezvoltare a unui sistem de ORM (Object Relational

Mapping) care să implementeze cele patru funcţii principale de lucru cu baza de date, select, update,

insert, delete.

El presupune familiarizarea cu API-urile de JDBC şi de Reflection, implementarea mini

ORM-ului şi dezvoltarea unei aplicaţii de test pentru acesta.

Alegerea acestui proiect se datorează lucrului cu astfel de sisteme , dar fără să fi avut o

înţelegere de ansamblu asupra funcţionării interne.

Pentru dezvoltarea aplicaţiei am folosit limbajul de programare Java, API-uri pentru JDBC,

Reflection, SWT şi creare de PDF şi ca sisteme de management al bazelor de date am ales cele mai

reprezentative două sisteme PostgreSQL şi Microsoft Sql Server.

Page 5: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

Notaţii şi Abrevieri

API – Application Programming Interface

AWT – Abstract Window Toolkit

DB – Database

GWT – Google Web Toolkit

IDE – Integrated Development Environment

JDBC – Java Database Connectivity

JPA – Java Persistance API

JVM - Java Virtual Machine

J2EE – Java Enterprise Edition

J2ME – Java Micro Edition

J2SE – Java Standard Edition

MVC – Model View Controller

ORM – Object Relational Mapping

PDA – Personal Digital Assistant

PK – Primary Key

POO – Programare Orientată pe Obiecte

SGBD – Sistem de Gestiune a Bazelor de Date

SQL – Structured Query Language

SWT – Standard Widget Toolkit

Page 6: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

6

Listă de figuri

Fig. 1.1 ORM –legătura dintre obiecte şi SGBD p9

Fig 2.1. Fluxul de compilare şi rulare al unei clase p12

Fig. 3.1. Meniul Source p14

Fig. 3.2. Fereastră generare getteri/setteri p14

Fig. 3.3. Meniu apărut la apăsarea combinaţiei de taste p15

Fig. 3.4. Paletă de componente p19

Fig. 3.5. Paletă de elemente în SWT p20

Fig. 3.6. Exemplu de casetă cu proprietăţile unui element p20

Fig. 3.7. Clasă pentru dezvoltarea în mediul grafic p21

Fig. 4.1. Arhitectura unei aplicaţii complete ce foloseşte un ORM p24

Fig. 4.2. Organizarea internă a proiectului p24

Fig. 5.1. Fereastra principală p38

Fig. 5.2. Fereastra de categorii p39

Fig. 5.3. Fereastra pentru medici de familie p39

Fig. 5.4. Vizualizarea programărilor p41

Fig. 5.5. Medicină naturistă p42

Fig. 5.6. Medicină Veterinară p42

Fig. 5.7. Farmacist p43

Fig. 5.8. Fereastra pentru programare p44

Fig. 5.9. Mesaj în cazul în care programarea s-a făcut cu success p44

Fig. 5.10. Mesaj în cazul în care programarea nu este posibilă p45

Fig. 5.11. Coloanele tabelului rețete p45

Fig. 5.12. Clasa Reteta ce mapează tabelul retete p46

Page 7: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

7

Listă de secvenţe

Secvenţa 4.1.- Date pentru conexiunea la bază p27

Secvenţa 4.2. – Formarea parametrilor şi stabilirea conexiunii p28

Secvenţa 4.3. – Extragerea unei adnotări prezente pe clasă şi studierea parametrului acesteia p28

Secvenţa 4.4. – Extragerea valorii id-ului p29

Secvenţa 4.5. – Studiul adnotării Column pentru maparea unui câmp p30

Secvenţa 4.6. – Obţinerea valorii id-ului p30

Secvenţa 4.7. –Instanţierea unui obiect folosind Reflection p31

Secvenţa 4.8. –Metoda delete(Object) p31

Secvenţa 4.9. – Studiul ordinii coloanelor p32

Sevenţa 4.10. – Metoda save(Long, List) p32

Secvenţa 4.11. – Tratarea obiectelor de tip String şi Date p32

Secvenţa 4.12.- Tratarea ultimei poziţii la update p33

Secvenţa 4.13. – Tratarea ultimei poziţii la insert p33

Secvenţa 4.14. – Metode generice p34

Secvenţa 4.15. – Exemplu de apel metodă generică p34

Secvenţa 4.16. – Extragerea numelui coloanei cu id-ul p34

Secvenţa 4.17. – Formarea listei cu numele coloanelor p35

Secvenţa 4.18. – Exemplu de utilizare listă de nume coloane p35

Secvenţa 4.19. – Generarea id-ului p36

Secvenţa 4.20. – Adnotarea Table p36

Secvenţa 4.21. – Adnotarea PK p37

Secvenţa 4.22. – Adnotarea Column p37

Secvenţa 4.23. – Adnotarea NotPersistent p37

Secvenţa 4.24. – Adnotarea NotNull p37

Secvenţa 4.25. – Adnotarea FK p38

Secvenţa 5.1. – Salvarea unei reţete p40

Secvenţa 5.2. – Exemplu de folosire readAll p41

Secvenţa 5.3. – Exemplu de folosire metoda read p43

Page 8: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

8

1. Introducere

1.1 Contextul

Încă de la apariţia modelului de baze de date relaţionale programatorii au simţit

nevoia să sporească posibilităţile acestui model şi să-l facă mai flexibil. Un salt uriaş în acest

sens a fost făcut în anii ’90, atunci când limbajele orientate-obiect au început să capete o

influenţă tot mai mare.

O primă încercare de a lega obiectele din POO cu tabelele unei baze de date a fost

făcută în anul 1992 de compania NeXT (companie înfiinţată de Steve Jobs la mijlocul anilor

’80). Soft-ul dezvoltat nu era un ORM în adevăratul sens al cuvântului, el fiind mai apropiat

de JDBC-ul din Java. Acest sistem purta denumirea de DbKit şi reprezenta un layer de

abstractizare, care asemănător JDBC-ului de astăzi permitea accesul la diferite baze de date

fără obligativitatea de a scrie cod specific bazelor de date. Pornind de la acest sistem,

dezvoltatorii de la NeXT au lansat mai apoi un framework de ORM complet.

Totuşi, primul sistem ce poate fi considerat un ORM a fost dezvoltat pentru limbajul

SmallTalk de o mică firmă din Canada şi s-a numit TopLink. În 1996 a apărut şi prima

versiune pentru Java.

Prima versiune de TopLink permitea printre altele:

a) să mapeze câmpurile bazei de date pe atributele obiectelor

b) să realizeze conversie între tipurile atributelor şi tipurile câmpurilor pe care se

mapează

c) posibilitatea de a mapa o înregistrare din baza de date pe mai multe obiecte

Deşi aparent dezvoltarea unui astfel de sistem pare că a venit de la sine, o perioadă

semnificativă de timp s-a lucrat la rezolvarea conflictelor dintre limbajele orientate-obiect şi

sistemele de gestiune ale bazei de date.

Este cunoscut faptul că o bază de date prezintă pentru fiecare tabel o cheie primară

care identifică în mod unic o înregistrare. Spre deosebire de înregistrările din baza de date,

obiectele din Java pot să fie identice, caz în care au aceaşi valoare şi aceeaşi adresă în

memorie, sau egale, având doar acceaşi valoare.

Alte diferenţe sunt legate de concepte precum moştenire, granularitate, asociere. În

ceea ce priveşte moştenirea, obiectele din Java acceptă moştenire simplă şi preiau atributele şi

metodele obiectului moştenit. În schimb, bazele de date nu cunosc noţiunea de moştenire.

Conceptul de asociere se referă la modul de legare a două entităţi fie în Java, fie în

baze de date. Dacă în Java asocierile sunt unidirecţionale, în baze de date acestea sunt

bidirecţionale şi se fac prin intermediul cheii externe. În cazul în care se doresc legături

bidirecţionale în Java, se poate declara în fiecare obiect un câmp de tipul celuilalt obiect.

Granularitatea se referă la problema legată de numărul de obiecte din model

comparativ cu numărul de tabele din bază. Pentru a se putea face maparea obiectelor pe baza

de date este necesară existenţa unei corespondenţe. Prin urmare cele două numere trebuie să

fie egale.

Page 9: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

9

1.2 ORM (Object Relational Mapping)

După cum am precizat, ORM-ul a apărut în perioada în care limbajele de programare

orientate obiect au căpătat un avânt deosebit, fiind principalele limbaje de dezvoltare datorită

flexibilităţii şi uşurinţei de dezvoltare. Cu toate acestea necesitatea comunicării cu un sistem

de gestiune a bazelor de date a determinat piaţa IT să găsească soluţii de comunicare între

obiectele create şi tabelele bazei de date, precum şi găsirea de soluţii pentru conflictele de

incompatibilitate dintre cele două tehnologii.

Astfel, el reprezintă un nivel de legătură între cele cele două modele:

Fig. 1.1 ORM –legătura dintre obiecte şi SGBD

Din figura de mai sus se observă corespondenţa Obiect A – Tabel A , respectiv Obiect B –

Tabel B.

Deşi faptul că asigură comunicarea cu baza de date este un aspect foarte important,

ORM-ul mai are o serie de avantaje precum :

a) Independenţa faţă de baza de date – acest fapt reprezintă un avantaj major al

sistemului ORM deoarece nu contează sistemul de management al unei baze de date

relaţionale folosit, în Java codul folosit va fi acelaşi, metodele nu vor avea alţi parametri sau

nu vor avea alte rezultate. Schimbarea sistemului de management al bazei de date nu va

determina schimbarea vreunei linii de cod în Java.

b) Simplitatea – Este mult mai uşor de lucrat cu obiecte în Java şi de folosit

principiile POO decât lucrul cu cod SQL. În SQL, atunci când se depăşeşte un anumit grad de

dificultate lucrurile pot deveni foarte încurcate, pe când în Java tot timpul vor fi mai uşor de

prelucrat datele şi de folosit aşa cum ne dorim.

c) Scalabilitate – Sistemul va funcţiona la fel indiferent de dimensiunea bazei de

date, a tabelelor sau a tipurilor de date folosite

Obiect A

Obiect B

SGBD ORM

TABEL A

TABEL B

Page 10: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

10

d) Rapiditate – Operaţiile dorite se vor executa într-un timp foarte scurt, rezultatele

vazându-se imediat

e) Un mare avantaj pentru programator este reprezentat şi de faptul că nu va mai fi

nevoit să realizeze o conexiune de fiecare dată şi să apeleze la concepte de JDBC, conexiunea

se va face automat când va fi nevoie iar datele vor fi salvate în obiecte.

f) Întreţinerea codului şi depanarea lui va fi foarte uşoară având în vedere cantitatea

de cod mult redusă şi uşurinţa cu care acesta poate fi înţeles.

1.3 Motivaţia dezvoltării unui sistem de ORM

De-a lungul timpului, atât în calitate de student cât şi în calitate de programator, am

avut ocazia să folosesc mai multe sisteme de mapare a obiectelor pe tabelele unei baze de

date. Dintre acestea cele mai cunoscute sunt Hibernate şi JPA(Java Persistence Api).

Deşi ştiam să folosesc un ORM, nu înţelegeam pe deplin tot ce se întâmplă în spate,

iar realizarea acestei lucrări a fost o bună oportunitate să studiez şi să încerc să rezolv

problemele ce pot apărea la un astfel de sistem.

Două probleme pe care eu le-am întâlnit şi pe care le-am considerat mai importante,

necesitând o atenţie mai deosebită erau reprezentate de maparea cheii primare şi

compatibilitatea şirurilor de caractere.

La maparea cheii primare apar de fapt două probleme ce trebuie rezolvate:

Prima din ele este necesitatea specificării printr-un parametru a numelui coloanei din

bază sau numele câmpului trebuie să se potrivească cu numele coloanei din tabel. Prin

soluţia propusă am făcut să nu mai fie necesară potrivirea de nume, am considerat că

tratarea cheii primare ar trebui să fie una specială, în sensul că ar trebui sa fie mai uşor

de mapat, nu mai greu după părerea mea, ca în Hibernate.

A doua problemă la maparea cheii primare este şi cea care face ca maparea să fie mai

dificilă, şi anume generarea id-urilor atunci când se face un insert. În Hibernate practic

trebuia mapată şi o secvenţă pentru generarea id-urilor. De asemenea, neplăceri mai

apăreau şi dacă se făceau insert-uri în sesiuni diferite de lucru,generarea secvenţei

făcându-se de la o valoare cu 50 mai mare faţă de valoarea cu care s-a început

sesiunea precedentă. Astfel, dacă se făceau într-o sesiune de lucru mai mult de 50 de

insert-uri apăreau probleme în sesiunea următoare deoarece se încerca o inserare cu un

id care deja exista. Eu am încercat ca prin simpla mapare cu o adnotare generarea să se

facă automat în raport cu valoarea maximă din tabel indiferent de sesiunea de lucru.

La compatibilitatea şirurilor de caractere, Hibernate impune o limitare de 255 de

caractere. Dacă se folosesc şiruri de caractere mai mari, este necesar la mapare să se

precizeze şi dimensiunea şirului. Am făcut ca şirurile de caractere să fie compatibile fără a

fi nevoie de o mapare specială în cazul unor dimensiuni mai mari.

Page 11: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

11

Deşi am utilizat mai multe astfel de sisteme de ORM, am ales să mă raportez la Hibernate

deoarece este cel mai popular dintre ele şi totodată cel mai complet sistem de acest gen

existent pe piaţă, acesta fiind şi sistemul cu care eu m-am iniţiat în tainele folosirii ORM-

urilor.

1.4. Descrierea proiectului

Proiectul presupune dezvoltarea unui mini sistem de mapare a obiectelor pe tabelele

din baza de date. Totuşi el trebuie să permită maparea obiectelor pe orice sistem de

management al bazelor de date relaţionale, fără impunerea unui anumit sistem. Totodată, el

trebuie să poată să facă conversie între tipurile proprietăţilor din obiectele Java şi tipul

câmpurilor din tabele.

Acest mini ORM trebuie să implemeteze principalele operaţii pe baza de date,

cunoscute în limbajul SQL ca: SELECT, DELETE, UPDATE, INSERT. Metodele asociate

acestor operaţii sunt:

pentru SELECT

a) read(Object) –această metodă primeşte ca parametru un obiect al cărui id este

cunoscut şi returnează din baza de date valorile câmpurilor pentru înregistrarea

cu id-ul id

b) readAll(Object) – această metodă primeşte ca parametru un obiect care

corespunde unui tabel din bază şi returnează toate înregistrarile din respectivul

tabel.

pentru DELETE

delete(Object) – această metodă primeşte ca parametru un obiect cu id

cunoscut şi şterge din bază înregistrarea din tabelul asociat obiectului, care are

id-ul id.Această metodă nu returnează nici un rezultat.

pentru UPDATE şi INSERT

save(Object) – această metodă primeşte ca parametru obiectul care trebuie

salvat. Această metodă reprezintă de fapt saveOrUpdate pentru că în urma

analizării id-ului obiectului el ştie dacă să facă Update sau să facă Insert. Astfel

dacă id-ul obiectului este null, ceea ce înseamnă că obiectul nu conţine date, se

va face un insert în bază. În caz contrar se va face un Update.

Proiectul presupune rescrierea de la capăt a metodelor de lucru pe bazele de date şi

nu doar apelarea unor metode existente din alte sisteme asemănătoare.

În procesul dezvoltării acestui sistem, dezvoltatorul este nevoit să facă apel la noţiuni

precum:

a) Reflection pentru studierea conţinutului claselor

b) JDBC – pentru realizarea conexiunilor cu baza de date

Pentru a demonstra avantajul sistemului este neesară realizarea unei aplicaţii de test

care să permită tipuri de date multiple. Această aplicaţie are ca tematică medicina şi se ocupă

Page 12: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

12

în principiu de reţete medicale, programări la doctor şi vizualizarea acestora şi este dezvoltată

folosind API-ul de SWT.

2. Alegerea Platformei

O platformă este un mediu hardware sau software în care poate fi rulat un program.

Platforma aleasă pentru dezvoltarea ORM-ului este platforma Java. Aceasta este o platformă

software.

Alegerea acestei platforme se justifică prin multitudinea de avantaje pe care le pune la

dispoziţia dezvoltatorului:

este portabilă,

rulează pe orice sistem de operare(Windows, Linux , Solaris, Mac OS) datorită

interpretorului integrat ce furnizează cod nativ al respectivului sistem

Alte motive sunt reprezentate de faptul că limbajul Java este orientat obiect ceea ce permite

refolosirea codului şi duce la micşorarea semnificativă a dimensiunii codului, este robust şi nu

în ultimul rând este simplu de utilizat.

Platforma Java are două componente:

a) Maşina virtuală Java (Java Virtual Machine) – Este componenta platformei

care face posibilă neutralitatea faţă de arhitectura folosită. La compilarea fişierelor .java ce

conţin codul sursă se creează nişte fişiere cu extensia .class care conţin secvenţe de bytecodes.

Java bytecodes reprezintă instrucţiuni în limbaj maşină pentru JVM (Java Virtual Machine).

La stadiul actual instrucţiunile nu sunt încă destinate procesorului. Pentru a putea fi

transformate în cod înţeles de procesor este necesară o tranformarea din bytecodes în cod

nativ al platformei hardware prin intermediul Interpretorului integrat în structura JVM

Fig 2.1. – Fluxul de compilare şi rulare al unei clase

b) A doua componentă a platformei Java este API – ul de Java (Application

Programming Interface) – Acesta reprezintă o colecţtie de librării ce ajută la dezvoltarea mai

uşoară a programelor. API-ul de Java este structurat în pachete, fiecare pachet înglobând

metode, constante, parametri utilizaţi de către programatori în crearea obiectelor şi structurilor

proprii.

În continuare voi dezvălui câteva avantaje ce justifică alegerea unei astfel de

platforme. Ele sunt după cum urmează:

Clasă.java

Compilare

Clasă.class(

bytecodes) JVM

Cod maşină

Page 13: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

13

a) Simplitatea – Java a fost proiectat să fie un limbaj simplu de utilizat şi înţeles, el poate

fi asimilat cu usurinţă de către programatori, mai ales dacă aceştia au ceva experienţă si cu

C++.

b) Java este un limbaj orientat obiect – Oferă un grad ridicat de abstractizare şi

încapsulare. Aest lucru duce la performanţe de securitate crescute, programatorul putând face

vizibile doar informaţiile pe care le doreşte din interiorul obiectelor şi folosind pentru acest

lucru metode dedicate accesării informaţiilor.

c) Lucrul cu memoria este mult îmbunătăţit, acest lucru datorându-se în mare parte

faptului că nu mai există pointeri definiţi de programator. Aceştia erau o sursă bogată de erori

atunci când se făcea accesul la memorie în C/C++. Limbajul introduce de asemenea un sistem

automat numit Garbage Collector care urmăreşte structura memoriei şi observă obiectele

neutilizate urmând să elibereze zona ocupată de respectivele obiecte şi evitând astfel

fragmentarea memorie.

d) Principalul avantaj îl reprezintă portabilitatea. – Un cod scris corect în limbajul Java ar

trebui să ruleze pe orice platformă hardware fără nici o problemă. Acesta reprezintă un

avantaj major chiar şi în faţa unor limbaje care pot rula mai repede aşa cum este C/C++. Este

adevărat că Java consumă mai multă memorie şi rulează într-un timp puţin mai mare decât

C/C++ dat fiind faptul că este atât un limbaj compilat cât şi un limbaj interpretat. Totuşi în

ziua de azi diferenţele nu mai sunt aşa mari ca la începuturile limbajului Java, iar

portabilitatea limbajului Java eclipsează micul avantaj al C++. În cazul în care un program

dezvoltat în C++ ar trebui portat pe altă platformă ar fi necesare modificări majore în cod.

În dezvoltarea ORM – ului am ales platforma Java Standard Edition din cele trei

platforme oferite de Java, celelale două fiind Java Micro Edition (platformă destinată

dispozitivelor mobile aşa cum sunt PDA – uri sau telefoane mobile) şi Java Enterprise Edition

(platformă destinată sistemelor de calcul distribuite sau de mari dimensiuni), deoarece se

pretează cel mai bine cerinţelor proiectului fiind o platformă specifică aplicaţiilor desktop.

3. Tehnologii folosite

În dezvoltarea acestui ORM am folosit:

un IDE(Mediu Integrat de Dezvoltare),

două sisteme de management ale bazelor de date relaţionale

patru API–uri necesare dezvoltării sistemului și testării acestuia.

3.1. IDE (Mediu integrat de dezvoltare)

Ca mediu integrat de dezvoltare am folosit Eclipse versiunea 4.2.2 (Eclipse Juno) care

poate fi descărcată gratuit de pe site – ul cu acelaşi nume. Am făcut această alegere deoarece

este un IDE foarte popular care oferă numeroase facilităţi cum ar fi generarea automată de

cod, formatarea automată a codului şi folosirea scurtăturilor de taste pentru îndeplinirea mai

multor acțiuni precum importuri de pachete necesare.

Page 14: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

14

Cele mai folosite faciliăţi din cele amintite mai sus sunt generarea automată a codului

şi realizarea importurilor necesare. Generarea automată de cod se referă în general la

generarea de constructori cu sau fără parametri și generarea de getteri și setteri. Există două

modalităţi de generare a getteri – lor și setteri – lor:

a) Din meniul Source se alege opţiunea „Generate Getters and Setters...”. În

fereastra deschisă se pot alege câmpurile pentru care să se genereze getteri şi setteri.

Fig. 3.1. –Meniul Source

b) A doua metodă foloseşte combinaţia de taste ALT+S după care se apasă tasta „R”.

După apăsarea tastelor se va deschide aceeaşi fereastră ca la punctul anterior.

Fig. 3.2. – Fereastră generare getteri/setteri

Page 15: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

15

De asemenea există două modalităţi de generare a constructorilor:

a) Din meniul Source se alege una din opţiunile „Generate Constructor using

fields...” sau „Generate Constructors from Superclass...”. În primul caz se pot alege câmpurile

ce vor fi introduse în construcor, iar în cel de – al doilea se generează un constructor moştenit

de la clasa Object.

b) A doua metodă foloseşte combinaţia de taste ALT+S şi după aceea se apasă

tasta C. Prin această combinaţie se deschide o listă similară cu cea a meniului Source din care

dezvoltatorul poate alege opţiunea cea mai convenabilă.

Fig. 3.3. – Meniu apărut la apăsarea combinaţiei de taste

Realizarea importurilor pachetelor se face prin combinaţia de taste

CTRL+SHIFT+O. După apăsarea lor, Eclipse va face toate importurile necesare în clasa în

care ne aflăm. O altă combinaţie de taste utilă este CTRL+SHIFT+F, combinație ce realizează

formatarea codului.

În cazul unei erori de cod, precum greşirea numelui unei variabile sau atunci când nu

se cunosc toţi parametri unei metode se poate folosi combinaţia de taste CTRL+1 (Quick Fix)

care îţi afişează o listă cu soluţii posibile la problemă.

Un alt avantaj al folosirii acestui IDE îl reprezintă multitudinea de plug–in–uri

disponibile gratuit ce vin în ajutorul dezvoltatorului. Din cele mai importante amintim plug-

in–ul pentru dezvoltarea de aplicații pe platforma Android, plug-in-ul pentru interfețe web de

la google(GWT), plug-in-ul pentru SWT.

Page 16: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

16

3.2. Sisteme de management ale bazelor de date relaționale

Am ales ca sisteme de management ale bazelor de date relaționale PostgeSQL și

Microsoft SQL Server 2012 deoarece sunt printre cele mai importante și utilizate sisteme de

acest gen.

3.2.1 PostgreSQL

PostgreSQL este probabil cel mai apreciat sistem de management al bazelor de date

relaționale datorită faptului că este disponibil pentru toate marile platforme(Windows, Linux,

Mac OS X) și este de asemenea apreciat pentru stabilitate, integritatea datelor și corectitudine.

Oferă posibiliatea stocării de imagini, sunete și chiar clipuri video. De asemenea PostgreSQL

este compatibil și cu PL/SQL de la Oracle. Succesul se datorează și faptului că sistemul este

gratuit și open-source.

Un alt avantaj al PostgreSQL este faptul că oferă interfețe de lucru cu numeroase

limbaje de programare așa cum sunt Java, C++, .NET, PHP, Perl etc.

Lucrul ce a determinat ca PostgreSQL să fie cel mai apreciat astfel de sistem atât de

către mari companii cât și de utilizatorii de zi cu zi este reprezentat de limitările pe care

sistemul le impune: dimensiunea unui tabel poate atinge 32TB, dimesiunea unei înregistrări

1,6 TB, numărul de înregistrari poate fi nelimitat, dimesiunea bazei de date poate fi

nelimitată, numărul de coloane poate ajunge la 1600 în funcție de tipul de date și nu în ultimul

rând numarul de indecși pentru un tabel este nelimitat.

3.2.2 Microsoft SQL Server

Microsoft SQL Server este un sistem de management al bazelor de date relaționale

dezvoltat de Microsoft. Având în vedere popularitatea sistemului de operare al celor de la

Microsoft și sistemul de management al bazelor de date relaționale dezvoltat de ei este unul

dintre cele mai populare, unul din dezavantaje fiind că este disponibil doar pentru sistemele de

operare de la Microsoft. Sistemul nu este open-source, există unele variante gratuite dar la

care se limitează dimensiunea bazei de date la 10 GB. Pentru o variantă plătită dimensiunea

bazei de date este de 540 PB.

Un motiv pentru care Microsoft SQL Server este popular deși este funcțional doar pe

sistemele de operare de la Microsoft sunt limitările pe care le impune, pe lângă dimesiunea

bazei de date mai sus amintită sistemul impune următoarele limitări: dimesiunea unei

înregistrări este nelimitată, numărul de coloane pentru fiecare tabel poate ajunge la 30000,

numărul maxim de caractere al numelui unei coloane este de 128, iar dimesiunea maximă a

unui tabel corespunde cu dimensiunea maximă a bazei de date.

Un alt avantaj al Microsoft SQL Server este integrarea cu celelalte unelte software

dezvoltate de Microsoft, care sunt foarte populare, astfel o persoană sau o companie care

utilizează software Microsoft nu va avea nevoie de modificări mari sau de upgrade-uri ale

sistemelor deja existente atunci când vor dori instalarea acestui sistem de management al

bazelor de date. Microsoft SQL Server oferă interfață de lucru cu toate limbajele suportate de

platforma .NET cum ar fi: C#, J#, Visual Basic, C++, F# etc.

În afara limbajelor suportate de platforma .NET Microsoft SQL Server mai oferă

interfață de lucru cu Java, cu ajutorul unui driver de JDBC, aceasta fiind o tehnologie pe care

o vom trata mai târziu.

Page 17: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

17

Am ales aceste două sisteme deoarece le-am considerat reprezentative pentru

sistemele de management ale bazelor de date existente.

3.3. API-uri folosite

În dezvoltarea acestui ORM am folosit patru API-uri: API-ul de JDBC oferit de

platforma Java, API-ul de Reflection, API-ul de SWT(Standard Widget Toolkit) şi API-ul

pentru generarea de PDF-uri.

3.3.1 API-ul de JDBC(Java Database Connectivity)

JDBC este un API dezvoltat de compania Oracle care ajută la lucrul cu o bază de

date scriind cod Java. Acest API are suport pentru executarea a diferite operații pe baza de

date cum ar fi INSERT, UPDATE, DELETE, SELECT.

În continuare voi prezenta modul de lucru cu JDBC și pașii necesari extragerii unui

set de date din bază sau executării oricărei alte operații pe baza de date. Vom presupune că

avem deja o bază de date formată.

Mai întâi de toate este necesară descărcarea driver-ului specific bazei de date pe care

o folosim și includerea lui în proiectul nostru.

Următorul pas este încărcarea driver-ului din cod cu ajutorul metodei

forName(„numele driverului”) aplicată pe un obiect Class în felul următor:

Class.forName(„numele driverului”). Aceasta metodă va căuta driver-ul, iar dacă acesta nu

există va genera o excepţie corespunzătoare.

În continuare este necesară stabilirea conexiunii cu baza de date. Pentru acest lucru

va trebui să cunoaştem:

utilizatorul bazei de date,

parola pentru accesul la baza de date

url-ul bazei de date împreună cu numele acesteia.

Stabilirea conexiunii se face prin aplicarea metodei getConnection pe un obiect de tip

DriverManager în felul următor:

DriverManager.getConnection(url, utilizator, parolă) în cazul majorităţii sistemelor

de management ale bazelor de date aşa cum este şi PostgreSQL,

pentru Microsoft SQL Server se foloseşte metoda getConnection( şir ), care după

cum se poate observa primeşte un singur parameru de tip String care conţine toate

datele necesare stabilirii conexiunii. Această metodă va returna un obiect de tip

Connection. Dacă conexiunea nu se realizează se va genera o excepţie în

concordanţă cu problema apărută.

După stabilirea conexiunii vom scrie interogarea pentru acţiunea ce urmează să o

executăm pe baza de date. Aceasta va fi reţinută într-o variabilă de tip String. Pentru

executarea interogării sunt necesari doi paşi.

Page 18: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

18

În primul rând este necesară crearea unui obiect de tip Statement pe baza conexiunii

deja create. Pot exista trei tipuri de acest fel:

Statement care atunci când este folosit încarcă în memorie de fiecare dată

interogarea,

PreparedStatement care încarcă o singură dată interogarea în memorie şi o

păstrează acolo,

CallableStatement care este folosită atunci când se apelează proceduri stocate

ale bazei de date.

În dezvoltarea proiectului am folosit un obiect de tip Statement. Apoi vom aplica

obiectului de tip Statement metoda executeQuery care va primi ca parametru variabila de tip

String în care am reţinut interogarea.Dacă s-a făcut un SELECT rezultatele vor fi reţinute

într-un obiect de tip ResultSet. În cazul în care operaţia a fost una de tip UPDATE, INSERT

sau DELETE vom primi ca rezultat doar numărul de rânduri afectate de către operaţia noastră.

De asemenea cu ajutorul JDBC putem obţine informaţii si despre tabele, cum ar fi

numele coloanelor, tipul lor, numărul lor. Acest lucru se poate realiza folosind metoda

getMetaData() pe care o aplicăm pe un obiect de tip ResultSet. Meta datele sunt reţinute într-

un obiect de tip ResultSetMetaData.

Ultimul pas după ce ne-am îndeplinit scopul propus este închiderea conexiunii prin

aplicarea metodei close() asupra obiectului de tip Connection în care am reţinut conexiunea.

În cazul în care uităm să închidem conexiunea Garbage Collector-ul va închide respectiva

conexiune când eliberează memoria ocupată de obiecte ce nu mai sunt folosite. Totuşi nu se

încurajează lăsarea acestei probleme în seama collector-ului deoarece pot apărea alte

probleme.

3.3.2. API-ul de Reflection

Reflection este o tehnologie ce permite studiul structurii unui obiect şi modificarea

acesteia sau luarea de decizii în timpul rulării pe baza structurii din acel moment a obiectului.

În Java API-ul de Reflection permite studierea clasei unui obiect, a câmpurilor

acestuia, a constructorilor, a metodelor din clasă. Este posibilă aflarea de informaţii chiar şi

despre câmpurile private.

Despre clase putem afla informaţii cum ar fi adnotările care sunt folosite pentru clasa

respectivă, numele clasei, câmpurile clasei, metodele acesteia, constructorii acesteia, pachetul

din care face parte şi pachetele importate, interfeţele pe care le implementează.

Despre constructorul unei clase putem afla parametrii pe care acesta îi primeşte şi

putem crea noi instanţe ale obiectului studiat prin apelul metodei newInstance(). Aceasta se

aplică pe obiectul de tip Constructor în care am reţinut constructorul obiectului studiat.

Această metodă primeşte ca parametri exact ce parametri primeşte şi constructorul obiectului

studiat.

Atunci când vrem să aflăm informaţii sau să manipulăm câmpurile putem folosi

Reflection pentru a afla numele câmpurilor, adnotările ce sunt folosite pentru câmpul studiat,

tipurile acestora şi putem afla şi modifica valorile acestora.

Page 19: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

19

Pentru a afla informaţiile despre câmpurile private este necesar să folosim metoda

getDeclaredFields().Aceasta, spre deosebire de metoda getFields() care ne va returna un

vector ce va conţine doar câmpurile publice, ne va returna un vector cu toate câmpurile clasei

inclusiv cele private.

Despre metode putem afla parametri pe care aceasta îi primeşte şi tipul pe care

aceasta îl returnează. De asemenea cu ajutorul Reflection putem executa metode ale obiectului

cu ajutorul metodei invoke() care va primi ca parametri obiectul pentru care se execută

metoda şi parametrii pe care aceasta îi primeşte. Metoda invoke() va fi executată pentru

obiectul de tip Method în care am reţinut metoda.

Mai putem afla informaţii cum ar fii adnotările prezente pe parametri funcţiilor sau ai

constructorilor, adnotările de pe getteri şi setteri.

3.3.3. API-ul de SWT(Standard Widget Toolkit)

Standard Widget Toolkit este un plug-in destinat dezvoltării de interfeţe grafice.

Acest plug-in foloseşte componente native ale sistemului de operare pe care se face

dezvoltarea însă elementele grafice nu au un aspect învechit aşa cum ne-am aştepta. SWT se

vrea a fi o combinaţie între rapiditatea cu care sunt încărcate elementele native la AWT şi

aspectul plăcut al elementelor din Swing.

Dezvoltarea se poate face atât din mediul grafic (drag and drop dintr-o paletă de

elemente în fereastra noastră ) cât şi din cod. Varianta preferată de cei mai mulţi dintre

programatori este dezvoltarea în mediul grafic, rămânând ca în cod sa fie scrise doar

ascultătorii petru butoane şi celelalte elemente

grafice folosite.

Fig. 3.4. - Paletă de componente

Page 20: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

20

Fig. 3.5. - Paleta de elemente în SWT

Fig. 3.6. – Exemplu de casetă cu proprietăţile unui element

Prin adăugarea unui element din paletă în canvas, se va deschide automat o fereastră

de proprietăţi din care poate fi ajustat design-ul elementului respectiv.

Page 21: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

21

Pentru a putea folosi SWT este necesară instalarea plug-in-ului mai întâi deoarece

acesta nu este prezent în pachetul standard al Eclipse. Acest lucru se poate face foarte uşor din

Eclipse din meniul Help opţiunea „Install New Software...”. Plug-in-ul este gratuit şi open-

source. Plug-in-ul este dezvoltat de IBM şi de aceea nu vine împreună cu API-ul standard de

java, în API-ul standard de Java putem găsi Swing şi AWT, care sunt dezvoltate de compania

Sun, companie ce deţine drepturile asupra Java.

Pentru a putea folosi mediul grafic de dezvoltare este necesară crearea unui tip de

clasă ce poate fi găsit după instalarea plug-in-ului. Crearea acestui tip de clasă se face prin

click dreapta pe pachetul în care vrem să creem clasa, din meniul deschis alegem opţiunea

„New”, iar din submeniul deschis vom alege opţiunea „Other”. Din fereastra deschisă vom

alege tipul de clasă Application Window din folderul SWT aşa cum veţi vedea în imaginea

următoare.

Fig. 3.7. – Clasă pentru dezvoltarea în mediul grafic

3.3.4. API-ul pentru crearea de fişiere PDF

Pentru crearea de fişiere PDF am folosit API-ul iText. iText este o bibliotecă ce

permite crearea, citirea şi manipularea de fişiere PDF. Pentru instalarea lui este necesară

decărcarea arhivei de tip jar ce conţine biblioteca şi introducerea ei în proiect.

iText oferă numeroase facilităţi de formare a PDF-urilor:

a) se poate face gruparea mai multor elemente într-un paragraf sau într-o frază,

b) se pot seta fonturi pentru diverse elemente cum ar fi un titlu sau un paragraf,

c) se pot adăuga imagini, tabele,

d) se pot pune referinţe,

e) se poate face împărţirea pe capitole şi secţiuni.

f) de asemenea se poate scrie cu indici sau cu exponent sau se poate scrie textul

subliniat, tăiat, boldat sau înclinat.

Page 22: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

22

iText are elemente cu o structură ierarhică. Cea mai mică unitate din iText se

numeşte Chunk. Chunk-ul reprezintă un String căruia i se poate seta doar fontul. Chunk-urile

se pot organiza în structuri mai mari şi anume obiecte de tip Phrase.

Obiectele de tip Phrase permit definirea de spaţiere. Pentru definirea mai multor

atribute cum ar fi cele de stil se folosesc obiecte de tip Paragraph. Acestea sunt obiecte ce

moştenesc obiectele de tip Phrase.

O clasă de obiecte ce moşteneşte clasa Paragraph se numeşte Anchor şi permite

definirea de referinţe de la anumite porţiuni din text la alte porţiuni mai îndepărtate sau la care

se face referire în text. Obiectele de tip Paragraph se pot grupa în structuri de tip Chapter.

În iText mai putem întâlni obiecte de tip Section pentru definirea unei secţiuni, List

pentru realizarea de liste ordonate sau neordonate, obiecte de tip Font penru definirea de

fonturi.

4. Dezvoltarea aplicaţiei

Aplicaţia dezvoltată este reprezentată de un mini sistem de mapare a obiectelor din

Java pe tabelele unei baze de date, sistem denumit Object-Relational Mapping.

4.1. Cerinţele aplicaţiei

Scopul acestei lucrări îl reprezintă dezvoltarea unui sistem ORM care să fie uşor de

folosit şi înţeles.

Obiectivele acesti proiect sunt reprezentate de implementarea operaţiilor uzuale de

INSERT, UPDATE, DELETE, SELECT, iar mai apoi să poată fi folosite fără a mai scrie cod

SQL.

Un alt obiectiv îl reprezintă funcţionarea ORM-ului pe baza unor relaţii stabilite între

obiectele din Java şi tabelele din baza de date. Aceste relaţii se pot stabili fie prin folosirea

adnotărilor fie prin folosirea unor fişiere de configurare de tip properties sau xml. În această

lucrare am ales să folosesc varianta cu adnotări deoarece este varianta mai modernă şi care a

câştigat teren în faţa celei de-a doua în ultimii ani. De asemenea varianta cu asdnotări este

după părerea mea mai simplu de înţeles şi mai intuitivă.

După definirea relaţiilor dintre obiecte şi tabele se vor folosi doar obiectele şi

metodele implementate în ORM. ORM-ul trebuie să dispună de următoarele metode:

a) read(object) – citeşte toate câmpurile obiectului specificat din care iniţial este

cunoscut doar id-ul

b) readAll(object) – citeşte toate obiectele de tipul obiectului specificat fără vreo

clauză WHERE

c) delete(object) – şterge obiectul specificat din care iniţial este cunoscut doar id-ul

d) save(object) – dacă id-ul este null se va face un INSERT în baza de date, se vor

salva câmpurile obiectului specificat şi se va genera un id; dacă id-ul nu este null atunci se va

face un UPDATE în baza de date

Page 23: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

23

Conexiunea trebuie să fie realizată cu ajutorul unui fişier de configurări. Datele se

vor introduce o singură dată iar apoi pe baza lor conexiunea se va face automat.

4.2. Arhitectura

Noţiunea de arhitectură software se referă la componentele de nivel înalt ale unui

sistem software. Arhitectura defineşte atât modulele sistemului pe baza unui set de reguli şi

relaţiile care se stabilesc între acestea, cât şi proprietăţile pe care modulele şi relaţiile dintre

ele le deţin.

La cazul general, o arhitectură pentru un sistem software se compune din:

Componentă de comunicaţie cu exteriorul

Componentă ce se ocupă de logica de business a aplicaţiei

Componentă responsabilă cu păstrarea datelor

Componenta de comunicaţie cu exteriorul poate fi reprezentată în funcţie de tipul

aplicaţiei de pagini web, interfeţe grafice desktop ş.a. Prin intermediul acesteia utilizatorul

introduce date în sistem sau preia date din sistem.

Componenta responsabilă cu prelucrarea informaţiilor provenite de la utilizator sau a

informaţiilor ce îi vor fi returnate acestuia este componenta de logică de business şi reprezintă

partea centrală a aplicaţiei. Toate datele care circulă prin sistem sunt întotdeauna filtrate de

această componentă.

Componenta responsabilă de păstrarea informaţiilor în sistem este reprezentată de un

sistem de management al bazelor de date. Aceasta permite salvarea unei cantităţi mari de date,

preluarea datelor , actualizarea sau ştergerea acestora.

O astfel de arhitectură am folosit şi în dezvoltarea şi testarea proiectului de faţă. În

cazul acestui proiect am considerat pentru componenta de baze de date cele mai utilizate două

sisteme de management ale bazelor de date,PostgreSQL şi Microsoft SQL Server.

Componenta care se ocupă de comunicaţia cu exteriorul este reprezentată aici de o

aplicaţie grafică în care utlizatorul interacţionează cu restul aplicaţiei prin intermediul unor

formulare. Totuşi, această componentă poate fi reprezentată la fel de bine de orice altă

aplicaţie ce foloseşte o conexiune la baza de date.

Componenta de logică de business este reprezentată aici de ORM. Sistemul ORM

funcţionează ca o legătură între aplicaţie şi baza de date. Prin intermediul lui se preiau datele

de la aplicaţia grafică, pe care mai apoi le folosim pentru a accesa baza de date.Totodată el

permite salvarea informaţiilor introduse prin aplicaţie în baza de date sau poate extrage

informaţii din bază în funcţie de acţiunile făcute de utilizator. După preluarea datelor, ORM-

ul, le prelucrează şi le face disponibile pentru aplicaţie.

În imaginea de următoare am ilustrat arhitectura unui sistem complet din viaţa reală

în care se foloseşte un ORM.

Page 24: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

24

Fig. 4.1. - Arhitectura unei aplicaţii complete ce foloseşte un ORM

4.3 Strucura proiectului

Codul proiectului este organizat pe pachete în funcţie de funcţionalităţile pe care le

oferă.

Fig. 4.2. - Organizarea internă a proiectului

Bază de date

(PostgreSQL,

Microsoft Server

SQL, etc.)

Sistem Object-Relational

Mapping

(Insert, Update, Delete,

Read, Mapare tabele)

Aplicaţie , Interfaţă cu

utilizatorul

Page 25: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

25

Pachetul org.licenta.miniorm.connection se ocupă de realizarea legăturii cu baza de

date. Acest pachet conţine 3 fişiere:

connection_data.properties - conţine informaţiile necesare unei conexiuni cu baza de

date, nume bază, driver-ul pentru baza respectivă, nume utilizator şi parola acestuia

pentru conectare

DataConn.java – se ocupă de parsarea elementelor din fişierul properties

ConnectionDB.java –se ocupă de preluarea informaţiilor parsate de DataConn şi

stabilirea conexiunii cu baza

Pachetul org.licenta.miniorm.queryactions conţine clasa QueryActions.java care se

ocupă de implementarea operaţiilor SELECT, UPDATE,DELETE, INSERT pe baza de date

dar cu ajutorul jdbc-ului.

Pachetul org.licenţa.miniorm.annotations se ocupă de crearea tipurilor de adnotări.

Acesta conţine:

Table.java – defineşte structura adnotării pentru maparea obiectului pe tabel;

PK.java – defineşte structura adnotării pentru maparea id-ului obiectului pe cheia

primară din tabelul asociat, specificat de adnotarea anterioară;

Column.java – defineşte structura adnotării pentru maparea unei coloane oarecare pe

un câmp al tabelului asociat din bază;

NotPersistent.java – defineşte structura adnotării care se asigură că un câmp nu va fi

mapat pe o coloană din bază;

NotNull.java –defineşte structura adnotării care se asigură că o proprietate din obiect

nu poate fi nulă.

Pachetul org.licenta.miniorm.ormhandler conţine clasa OrmHandler.java care

implementează metodele read, readAll, delete, save utilizând metodele create în clasa

QueryActions.java şi parsând obiectul pentru obţinerea adnotărilor.

Acest pachet împreună cu pachetul de queryactions reprezintă centrul propriu zis aplicaţiei

şi ocupându-se de ceea ce înseamnă un orm.

Pachetul org.licenta.aplicatie.model conţine clasele model folosite pentru testarea

orm-ului dezvoltat:

Medic.java – este o clasă model ce conţine câmpurile:

a) idMedic – este de tip Long şi prezintă adnotarea PK

b) idCategorie – este de tip Long şi prezintă adnotarea Column; el face

legătura cu obiectul Categorie

c) numeMedic – este de tip String şi prezintă adnotarea Column

d) codIdentificare – este de tip String şi prezintă adnotarea Column

Page 26: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

26

Categorie Medic.java – este o clasă model pentru categoriile de medicină existentă şi

conţine câmpurile:

a) idCategorie – este de tip Long şi prezintă adnotarea PK

b) denumireCategorie – este de tip String şi prezintă adnotarea Column

Reteta.java –este o clasă model ce descrie câmpurile unei reţete medicale:

a) idReteta – este de tip Long şi prezintă adnotarea PK

b) idMedic – este de tip Long şi prezintă adnotarea Column; el face legătura

cu obiectul Medic

c) numePacient – este de tip String şi prezintă adnotarea Column

d) nrStrada – este de tip Long şi prezintă adnotarea Column

e) câmpurile varsta (de tip int), sex(de tip String), cetatenie(de tip String),

judet(de tip String), oras(de tip String), strada(de tip String), diagnostic(de

tip String), medicamente(de tip String), compensata(de tip Boolean),

data(de tip Date) nu prezintă nici o adnotare Column, iar numele

câmpului din baza va fi automat acelaşi cu numele proprietăţii din obiect

RetetaAnimal.java – este o clasă model ce descrie câmpurile unei reţete prescrise de

medicul veterinar:

a) idRetetaAnimal – este de tip Long şi prezintă adnotarea PK

b) idMedic – este de tip Long şi prezintă adnotarea Column; el face legătura

cu obiectul Medic

c) numePosesor – este de tip String şi prezintă adnotarea Column

d) nrTelefon – este de tip String şi prezintă adnotarea Column

e) tipAnimal –este de tip String şi prezintă adnotarea Column

f) varstaAnimal –este de tip int şi prezintă adnotarea Column

g) câmpurile tratament(de tip String), diagnostic(de tip String),

comentariu(de tip String), data(de tip Date) nu au adnotare, numele

câmpului din tabel fiind acelaşi cu numele proprietăţii din obiect

FormularMedicinaNaturista.java –este o clasă model ce descrie un formular pe care ar

putea să îl elibereze medicul naturist şi care conţine câmpurile:

a) idFormular – este de tip Long şi prezintă adnotarea PK

b) idMedic – este de tip Long şi prezintă adnotarea Column; el face legătura

cu obiectul Medic

c) numePacient – este de tip String şi prezintă adnotarea Column

d) problemeAnterioare –este de tip String şi prezintă adnotarea Column

Page 27: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

27

e) câmpurile varsta(de tip int), diagnostic(de tip String), remediu(de tip

String) ,data(de tip Date) nu au o adnotare, numele câmpului asociat din

tabel fiind acelaşi cu numele proprietăţii

Programare.java – este o clasă model ce descrie câmpurile unui formular de realizare a

unei programări la medic şi conţine cîmpurile:

a) idProgramare – este de tip Long şi prezintă adnotarea PK

b) numeMedic – este de tip String şi prezintă adnotarea Column; el face

legătura cu obiectul Medic

c) numePacient – este de tip String şi prezintă adnotarea Column

d) dataProgramare –este de tip Date şi prezintă adnotarea Column

e) oraProgramare –este de tip int şi prezintă adnotarea Column

Pentru a ne folosi de aceste obiecte şi a le pune la lucru am creat pachetele

org.licenta.aplicatie.medic, org.licenta.aplicatie.farmacist, org.licenta.aplicatie.pacient care

fac apel la aceste modele prin intermediul câmpurilor din interfeţele grafice.

Pentru lansarea proiectului este suficientă rularea clasei Proiect.java din pachetul

org.licenta.proiect care apelează prin elementele de interfaţă clasele corespunzătoare celor trei

pachete descrise anterior.

4.4. Funcţionalităţile sistemului și tratarea problemelor

Prima şi una din cele mai importante caracteristici ale sistemului ORM trebuie să fie

independenţa faţă de baza de date. Programatorul trebuie să poată să folosească ORM-ul în

acelaşi mod indiferent de sistemul de management al bazei de date folosit. Pentru realizarea

acestui lucru am ales să folosesc un fişier de configurare în care programatorul introduce

datele de logare în acelaşi mod indiferent de sistemul de management al bazei de date folosit.

Datele ce trebuie introduse în fişier sunt:numele driver-ului, url-ul bazei de date, numele bazei

de date, numele de utilizator şi parola. În continuare veţi vedea cum trebuie să arate conţinutul

unui astfel de fişier.

Secvenţa 4.1.- Date pentru conexiunea la bază

După introducerea datelor acestea vor fi preluate şi folosite pentru formarea

parametrilor necesari conectării. Formarea parametrilor este o parte foarte importantă

deoarece aceştia nu sunt la fel pentru toate sistemele de management ale bazelor de date

relaţionale. Formarea acestora diferă în special pentru Microsoft SQL Server.

1. driver = org.postgresql.Driver 2. url = jdbc:postgresql://localhost:5432/ 3. databaseName = aplicatie 4. userName = alin 5. userPassword = iomanigar

Page 28: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

28

Secvenţa 4.2. – Formarea parametrilor şi stabilirea conexiunii

După cum se poate observa în cazul Microsoft conectarea se face folosind un singur

parametru ce conţine toate datele de logare pe când la restul SGBD-urilor conectarea se face

folosind trei parametri. În cazul în care conexiunea nu s-a făcut cu succes se va primi un

mesaj corespunzător.

O altă parte importantă sistemului este implementarea celor patru operaţii:

read(object), readAll(bbject), delete(object), save(object).

Metoda read(Object) trebuie să citească toate câmpurile obiectului specificat din care

iniţial se cunoaşte doar id-ul. Această metodă, pe lângă studierea clasei cu ajutorul API-ului

de Reflection, se foloseşte de metoda read(Long) din clasa QueryActions ce returnează un

HashMap(conţine înregistrari de forma cheie=valoare) în care cheia este numele coloanei din

tabel şi valoarea este valoarea ce o are înregistrarea căutată în tabel. Pentru implementarea

acestei metode am folosit API-ul de JDBC.

Clasa QueryActions are ca şi câmp o variabila de tip String căreia i se asignează o

valoare la instanţierea unui obiect de tip QueryActions prin constructor.

Pentru maparea clasei pe tabel am folosit o adnotare denumită @Table. Aceasta

primește ca parametru un String ce reprezintă numele tabelului. O parte foarte importantă a

implementării este reprezentată de studierea adnotărilor. În rândurile următoare voi

exemplifica și explica modul de studiu al adnotărilor.

Secvenţa 4.3. – Extragerea unei adnotări prezentă pe clasă şi studierea parametrului acesteia

1. try { 2. 3. if(driverName.equals("com.microsoft.sqlserver.jdbc.SQLServerDriver")){ 4. String con =url+";databaseName="+databaseName+";user="+usrName+ 5. ";password="+usrPass; 6. connection = DriverManager.getConnection(con); 7. } else { 8. connection = DriverManager.getConnection(url+databaseName,usrName, 9. usrPass); 10. } 11. } catch (SQLException e) { 12. System.out.println("Conectarea nu a reusit!"); 13. }

1. public <T> String getTableName(T object) { 2. 3. Class objectClass = object.getClass(); 4. Annotation annotation =objectClass.getAnnotation(Table.class); 5. Table table = (Table) annotation; 6. String tableName = table.name(); 7. 8. return tableName; 9. }

Page 29: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

29

În liniile de cod de mai sus se află o metodă ce studiază dacă asupra clasei se afla

adnotări. La linia patru se poate observa că se extrag doar adnotările de tip Table iar la linia

șase se extrage numele tabelului ce va fi folosit mai departe.

O altă metodă folosită în metoda read este metoda getId. Aceasta extrage pe baza

adnotării @PK id-ul obiectului. Adnotarea @PK este folosită pentru a mapa cheia un câmp

din clasă pe cheia primară din tabel. În rândurile următoare se poate vedea modalitatea de

extragere a valorii id-ului.

Secvenţa 4.4. – Extragerea valorii id-ului

În liniile de mai sus se verifică două condiții necesare pentru a stabili dacă un câmp

este mapat corect pe cheia primară din tabel și anume să dispună de o adnotare de tip @PK si

să fie de tipul Long. Verificarea tipului este necesară deoarece tabele pot ajunge la dimensiuni

foarte mari, iar tipul Long oferă o gamă de valori suficient de mare pentru a permite un număr

mare de înregistrări.

În metoda read(object) primi paşi sunt reprezentaţi de folosirea celor două metode

mai sus menţionate pentru a afla numele tabelului pe care este mapată clasa şi id-ul obiectului.

Numele tabelului va fi folosit pentru a instanţia un obiect de tip QueryActions iar id-ul pentru

a extrage din baza de date înregistrarea cu id-ul dat ca parametru. Asignarea de valori

câmpurilor obiectului se face pe baza cheii din HashMap-ul rezultat în urma aplicării metodei

read(Long).

Maparea Câmpurilor din obiect pe coloanele tabelului se face cu ajutorul adnotării

@Column ce primește ca parametru numele coloanei.Maparea se poate face și pe baza

numelui câmpului dacă numele acestuia este același cu numele coloanei din baza de date. Mai

jos puteți vedea liniile de cod prin care se face maparea efectivă.

1. if (annot instanceof PK 2. && field.getType().getSimpleName().equals("Long")) 3. { 4. try { 5. id = (Long) field.get(object); 6. } catch (IllegalArgumentException e) { 7. e.printStackTrace(); 8. } catch (IllegalAccessException e) { 9. e.printStackTrace(); 10. } 11. 12. } 13. } 14. 15. return id;

Page 30: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

30

Secvenţa 4.5. – Studul adnotării Column pentru maparea unui câmp

Variabila annots din codul de mai sus reprezintă vectorul ce conține adnotările unui

câmp.

Adnotarea @NotPersistent ce apare în cod este folosită pentru câmpurile ce nu vor fi

folosite pentru persistența în baza de date.

Următoarea metodă implementată este readAll(object). Spre deosebire de metoda

anterioară, aceasta nu folosește metoda getId deoarece scopul ei este să citească toata obiecte

de tipul celui specificat, și nu unul anume. O metodă nouă folosită in dezvoltarea acesteia este

metoda getColumns din clasa QueryActions.

Metoda getColumns returnează o listă de String-uri ce reprezintă numele coloanelor

exact în ordinea în care acestea se găsesc în tabel. Această metodă este utilă deoarece pe baza

rezultatului returnat vom putea asigna valori câmpurilor din obiecte indiferent de ordinea în

care acestea sunt declarate. Astfel programatorul nu va fi obligat să știe exact ordinea

coloanelor din baza de date. O altă utilitate a acestei metode este și faptul că putem extrage

din lista rezultată numele coloanei ce conține id-ul, acest lucru fiind necesar deoarece

maparea câmpului pentru id se face doar cu adnotarea @PK, nespecificând numele coloanei

cu id-ul nicăieri în clasa noastră. În metoda readAll(object) am folosit această metodă pentru

cea de-a doua utilitate. Metoda getColumns a fost implementată cu ajutorul JDBC.

Secvenţa 4.6. – Obţinerea valorii id-ului

În codul de mai sus este exemplificată modalitatea de extragere a coloanei ce conține

id-ul.

1. if (annots.length == 0) { 2. colName = field.getName(); 3. } else { 4. 5. for (Annotation a : annots) { 6. if (a instanceof Column) { 7. 8. Column col = (Column) a; 9. colName = col.name(); 10. } else if (!(a instanceof NotPersistent)) { 11. 12. colName = field.getName(); 13. } 14. } 15. }

1. try { 2. Object firstKey = columns.get(0); 3. field.set(inst, help.get(i).get(firstKey)); 4. } catch (IllegalArgumentException|IllegalAccessException e) { 5. e.printStackTrace(); 6. }

Page 31: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

31

Acestă metodă returnează o listă cu obiectele de tipul celui specificat găsite în baza

de date. Aceste lucru se realizează cu ajutorul Reflection folosind metoda newInstance() pusă

la dispoiție de API-ul e Reflection. Pentru fiecare HashMap din lista de HashMap-uri

returnată de metoda readAll() din QueryActions se creează o noua instanță a obiectului

specificat.

Secvenţa 4.7. –Instanţierea unui obiect folosint Reflection

În afară de câmpul ce se mapează pe coloana ce conține id-ul restul coloanelor se

mapează similar cu cele de la metoda read(object).

Cea de-a treia metodă este cea care ne ajută la ștergerea unui obiect de tipul celui dat

ca parametru din baza de date, și anume metoda delete(object).

În această metodă am folosit două metode amintite mai devreme, getId() și

getTableName(), si o a treia metodă din clasa QueryActions.Această metodă din clasa

QueryActions se numește delete și primește ca parametru o variabilă de tip

Long(delete(Long)). Având în vedere că este o metodă de dimensiune mică voi pune mai jos

întreaga metodă.

Secvenţa 4.8. –Metoda delete(object)

Ultima metodă ce trebuie implementată este metoda save(object). Această metodă

trebuie fie să insereze o nouă înregistrare în baza de date dacă id-ul obiectului dat ca

parametru este null, fie să facă un update asupra obiectului din baza de date dacă id-ul este o

valoare ce există în baza de date.

Această metodă folosește metoda getId() pentru a afla id-ul obiectului dat ca

parametru, getTableName() pentru a afla numele tabelului în care se va face salvarea,

getColumns din clasa QueryActions. Aici metoda getColumns() este folosită petru a studia

ordinea coloanelor din tabel. Și nu în ultimul rând metoda save(Long, List<Object>) din clasa

QueryActions. Această metodată primește ca parametri id-ul înregistrării şi lista de valori pe

care să le insereze sau să le modifice în baza de date.

1. for (int i = 0; i < help.size(); i++) { 2. try { 3. inst = object.getClass().newInstance(); 4. } catch (InstantiationException | IllegalAccessException e) { 5. e.printStackTrace(); 6. }

...

..

1. public <T> void delete(T object) { 2. 3. Long id = getId(object); 4. 5. String tableName = getTableName(object); 6. 7. QueryActions action = new QueryActions(tableName); 9. action.delete(id); 10. }

Page 32: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

32

Secvenţa 4.9. – Studiul ordinii coloanelor

În liniile de cod de mai sus se află un exemplu de aflare a poziției unei coloane în

tabel. Variabila pos reprezintă poziția pe care va fi pusă valoarea câmpului obiectului în lista

de valori ce va fi trimisă ca parametru metodei save din QueryActions. În metoda save(object)

formăm din câmpurile obiectului dat ca parametru lista de valori necesară metodei save(Long,

List< Object >).

În rândurile următoare voi vorbi despre metoda save(Long, List< Object >) din clasa

QueryActions. În această metodă se folosesc alte două metode implementate în aceeași clasă:

update(Long, List< Object >) și metoda insert(List< Object >).

Sevenţa 4.10. – Metoda save(Long, List)

În aceste două metode partea cea mai dificilă și cea mai importantă a fost formarea

interogării. O atenție specială au necesitat obiectele de tip String și cele de tip Date.

Obiectele de tip String au valori ce sunt încadrate între ghilimele și nu toate sistemele

de gestiune a bazelor de date relaționale acceptă valori încadrate între ghilimele, însă absolut

toate acceptă încadrarea între apostrof. În liniile de cod următoare se va vedea cum am

înlocuit ghilimelele cu apostrof în cazul metodei update și cum am format interogarea, aceasta

trebuind să se formeze corect indiferent de numărul de elemente ale listei dată ca parametru.

Secvenţa 4.11. – Tratarea obiectelor de tip String şi Date

1. if (a instanceof Column) { 2. Column col = (Column) a; 3. colName = col.name(); 4. pos = coloane.indexOf(colName) - 1; 5. }

...

1. public void save(Long id, List<Object> valori) { 2. 3. if (id != null) 4. update(id, valori); 5. else 6. insert(valori); 7. }

1. if (valori.get(i).getClass().getName().equals("java.lang.String")) { 2. help += coloane.get(i) + "=" + "\'" + valori.get(i)+ "\', "; 3. } else if (valori.get(i).getClass().getName().equals("java.util.Date")) { 4. java.sql.Date data = new Date(((java.util.Date) valori.get(i)).getTime()); 5. help += coloane.get(i) + "=" + "\'" + data + "\', "; 6. } else { 7. help += coloane.get(i) + "=" + valori.get(i) + ", "; 8. }

Page 33: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

33

După cum se poate observa obiectele de tip Date trebuie convertite la un alt tip de

obiect Date care să fie compatibil cu cel din baza de date. De asemenea și valorile unor

asemenea obiecte trebuie încadrate cu apostrof. Diferența la metoda insert era că nu se adaugă

șiruri de caractere de forma nume_coloană=valoare, ci după valoare se pune caracterul

virgulă.

În ambele metode mai trebuie făcută o verificare, și anume dacă valoarea se află pe

ultima poziție în lista de valori, formarea interogării fiind puțin diferită.

Secvenţa 4.12.- Tratarea ultimei poziţii la update

Secvenţa 4.13. – Tratarea ultimei poziţii la insert

Secvențele de cod de mai sus ilustrează modul în care se formează interogarea

pentru ultima valoare din listă. Dupa cum se poate observa în prima secvență(extrasă din

metoda update) după ultima valoare urmează caluză WHERE pe când în cazul metodei insert

, ilustrată în cea de-a doua secvență de cod, după ultima valoare urmează închiderea unei

paranteze.

În cazul metodelor din clasa ORMHandler, și anume read(object), readAll(object),

delete(object), save(object), am implementat astfel încât acestea să accepte orice tip de obiect.

Acest lucru a fost realizat făcând ca aceste patru metode să fie generice, astfel ele putând

accepta orice tip de obiect.

1.if(valori.get(i).getClass().getName().equals("java.lang.String"2. )){ 3. help += coloane.get(i) + "=" + "\'" + valori.get(i) 4. + "\' WHERE " + idTabel + "=" + id; 5. } else if (valori.get(i).getClass().getName() 6. .equals("java.util.Date")){ 7. java.sql.Date data = new 8. Date(((java.util.Date)valori.get(i)).getTime()); 9. help += coloane.get(i) + "=" + "\'" + data + "\' WHERE " 10. + idTabel + "=" +id; 11. 12. }

1. if(lista.get(i).getClass().getName().equals("java.lang.String" 2. )) { 3. help += "\'" + lista.get(i) + "\') "; 4. } else if 5. (lista.get(i).getClass().getName().equals("java.util.Date")) { 6. java.sql.Date data = new 7. Date(((java.util.Date)lista.get(i)).getTime()); 8. help += "\'" + data + "\') "; 9. }

Page 34: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

34

Secvenţa 4.14. – Metode generice

Așa cum se poate observa în secvența de mai sus la toate cele patru metode

este prezent parametrul care devine tipul obiectului dat ca parametru. Acest lucru face ca

metodele să accepte ca parametru orice tip de obiect. Atunci când metodele sunt folosite nu

este nevoie de vreun apel special de metodă, se va apela pur și simplu prin numele metodei și

i se va da ca parametru orice tip de obiect se dorește. Mai jos voi ilustra apelul unei astfel de

metode.

Secvenţa 4.15. – Exemplu de apel metodă generică

După cum se poate observa faptul că metoda read(object) este una generică nu

complică deloc folosirea ei.

Prima problemă ce apare la maparea cheii primare este compatibilitatea numelui

câmpului sau cum putem indica cât mai simplu faptul că un câmp este corespondentul cheii

primare din tabel. În rezolvarea acestei probleme am plecat de la considerentul că pentru un

tabel prima coloană va fi tot timpul reprezentată de cheia primară.

Secvenţa 4.16. – Extragerea numelui coloanei cu id-ul

Mai sus se află una din secvenţele de cod ce rezolvă această problemă. Executarea

interogării din prima linie duce la reţinerea tuturor datelor despre tabel în variabila helpRs.

Extragerea metadatelor se face cu metoda getMetaData(). Metadatele reprezintă numele

coloanelor, tipurile acestora, numărul coloanelor etc. Metoda getColumnName(1) returnează

public <T> void save(T object)

public <T> List<T> readAll(T object)

public <T> void delete(T object)

public <T> void read(T object)

1. Serial serial = new Serial(); 2. serial.setId(2L); 3. ORMHandler h = new ORMHandler(); 4. h.read(serial);

1. String helpQuery = "SELECT * FROM " + this.table; 2. try { 3. 4. Statement helpStmt = connect.createStatement(); 5. ResultSet helpRs = helpStmt.executeQuery(helpQuery); 6. rsmd = helpRs.getMetaData(); 7. idTabel = rsmd.getColumnName(1); 8. 9. } catch (SQLException e) { 10. e.printStackTrace(); 11. System.out.println("Probleme la metadata!"); 12. }

Page 35: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

35

numele primei coloane din tabel, adică cea care conţine cheia primară. Menţionez că metoda

getMetaData returneză coloanele exact în ordinea în care ele se găesc în tabel.

O altă metodă de rezolvare folosită în implementarea sistemului este reţinerea tuturor

numelor coloanelor într-o listă şi folosirea primului element din listă atunci când avem nevoie

de coloana pentru cheia primară. Acest lucru se realizeaza cu ajutorul metodei getColumns

din clasa QueryActions.

Secvenţa 4.17. – Formarea listei cu numele coloanelor

Adăugarea acestei secvenţe de cod la secvenţa de mai devreme duce la formarea unei

liste cu numele coloanelor.

Un exemplu de folosire a celei de-a doua metode poate fi observat în metoa readAll.

Mai jos se află secvenţa de cod ce ilustreaza folosirea celei de-a doua metode.

Secvenţa 4.18. – Exemplu de utilizare listă de nume coloane

În liniile de cod de mai sus columns reprezintă lista cu numele coloanelor dintr-un

tabel. Numele primei coloane este extras şi este folosit pentru a se extrage valoarea cheii

primare dintr-un HashMap ce conţine înregistrări de tip cheie=valoare, cheia fiind numele

coloanei.

Cea de-a doua problemă la maparea cheii primare este generarea id-ului. Această

problemă a fost rezolvată ţinând cont doar de valoarea maximă a id-ului la un moment de

timp. Nu s-a ţinut cont de valoarea id-ului din sesiunile anterioare.

1. try { 2. for (int i = 1; i < rsmd.getColumnCount() + 1; i++) 3. rez.add(rsmd.getColumnName(i)); 4.} catch (SQLException e) { 5. e.printStackTrace(); 6. }

1. try { 2. Object firstKey = columns.get(0); 3. 4. field.set(inst, help.get(i).get(firstKey) 5. } catch (IllegalArgumentException| IllegalAccessException e) { 6. e.printStackTrace() 7. } 8. }

Page 36: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

36

Secvenţa 4.19. – Generarea id-ului

În liniile de mai sus se poate observa că este extrasă valoarea maximă a cheii primare

din tabel. La final valoarea maximă este incrementată, astfel asigurând unicitatea cheii

primare. Dacă în tabel nu există înregistrări nu reprezintă o problema deoarece valoarea este

iniţializată cu 0 şi este incrementată oricum la final, fie că a găsit valori sau nu în tabel.

Rezolvarea celei de-a doua probleme a fost mai facilă deoarece pentru maparea

oricărui tip de dată ce conţine caractere am folosit direct clasa String. În Hibernate atunci

când se preiau date din baza de date sunt salvate într-un array ce conţine date de tip char. Apoi

făcându-se cast-ul la String dacă este nevoie. De asemenea atunci când se salvează un şir de

caractere în baza de date acestea sunt convertite în array de char-uri si pentru acest lucru este

nevoia de specificarea lungimii dacă acesta depăşeşte 255.

O altă parte a acestei lucrări ce a rămas neatinsă sunt adnotările. Acestea reprezintă

metadate ce pot fi adăugate claselor, pachetelor, câmpurilor. Sunt caraterizate de prezenţa

caracterului „@” la început. Spre deosebire de comentarii ele sunt recunoscute de compilator

şi apar ca elemente şi in API-ul de Reflection. Aici am folosit adnotări pentru maparea

claselor şi câmpurilor pe tabele şi coloane. Ele pot conţine parametrii care de asemenea sunt

cunoscuţi şi pot fi utilizaţi în cercetarea claselor şi a câmpurilor. Pentru mapare am folosit

următoarele adnotări:

a) @Table – aceasta poate primește ca parametru numele tabelului e care se mapează

clasa. Implementarea adnotării poate fi observată ma jos.

Secvenţa 4.20. – Adnotarea Table

Adnotarea @Retention este folosită pentru a specifica momentul când să fie luată în

considerare adnotarea. Pentru toate adnotările implementate am ales să fie active la rulare

b) @PK – am folosit-o pentru a mapa cheia primară

1. Long idRow = 0L; 2. String helpQuery = "SELECT * FROM " + this.table; 3. try { 4. Statement helpStmt = connect.createStatement(); 5. resultSet = helpStmt.executeQuery(helpQuery); 6. while (resultSet.next()) { 7. Long idRow1 = resultSet.getLong(1); 8. if (idRow1 > idRow) 9. idRow = idRow1; 10. } 12. } catch (SQLException e) { 13. e.printStackTrace(); 14. System.out.println("Probleme la metadata!"); 15. } 16. idRow++;

@Retention(RetentionPolicy.RUNTIME) public @interface Table { String name(); }

Page 37: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

37

Secvenţa 4.21. – Adnotarea PK

Această adnotare nu primește nici un parametru.

c) Adnotarea @Column – folosită pentru a mapa orice câmp pe o coloană în cazul în

care numele coloanei şi cel al câmpului nu coincid.

Secvenţa 4.22. – Adnotarea Column

Primește ca parametru numele coloanei pe care se mapează și opțional tipul de date

și lungimea. Al doilea parametru și al treilea pot fi folosiți mai mult în cazul în care ORM-ul

creează și tabele și trebuie specificate tipurile coloanelor și lungimea dacă este vorba de date

de tip VARCHAR.

d) Adnotarea @NotPersistent – este folosită pentru a marca faptul că un câmp nu se

persistă în bază, astfel că el nu va fi luat în considerare la operațiile sistemului cu baza de

date.

Secvenţa 4.23. – Adnotarea NotPersistent

e) Adnotarea @NotNull – folosită în eventualitatea în care ORM-ul va genera și

tabele pentru a specifica la crearea tabelului că o coloană nu poate lua valori nule.

Secvenţa 4.24. – Adnotarea NotNull

@Retention(RetentionPolicy.RUNTIME) public @interface PK { }

@Retention(RetentionPolicy.RUNTIME) public @interface Column { String name(); String type() default "";

int length() default 100; }

@Retention(RetentionPolicy.RUNTIME) public @interface NotPersistent { }

@Retention(RetentionPolicy.RUNTIME) public @interface NotNull { }

Page 38: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

38

f) Adnotarea @FK – folosită la la crearea de tabele pentru a mapa cheia externă din

tabel. Primește ca parametru numele tabelului de care se leagă tabelul mapat de clasa în care

se află câmpul cu adnotarea @FK.

Secvenţa 4.25. – Adnotarea FK

5. Testarea aplicaţiei

Pentru testarea aplicaţiei am dezvoltat o mini-aplicaţie grafică prin intermediul căreia

incerc să demonstrez aplicabilitatea şi funcţionalitatea ORM-ului. În continuare voi prezenta

modul de folosire al aplicaţiei de testare:

5.1. Fereastra principală

Conţine câte un buton care deschide fiecare componentă a aplicaţiei: cea pentru

medici, cea pentru famacişti şi cea pentru pacienţi.

Fig. 5.1. – Fereastra principală

@Retention(RetentionPolicy.RUNTIME) public @interface FK { String name(); }

Page 39: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

39

5.2. Fereastra Medic

La apăsarea butonului Medic se va intra într-o fereastră de unde se poate alege

categoria din care face parte medicul, aplicaţia este destinată medicilor de familie, medicilor

naturişti şi medicilor veterinari.

Fig. 5.2. – Fereastra de categorii

La apăsarea butonului Medicină de familie se va deschide o fereastră de unde

medicul are posibilitatea de a elibera o reţetă şi de a vizualiza programările făcute de pacienţii

săi.

Fig. 5.3. – Fereastra pentru medici de familie

Page 40: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

40

Pentru eliberarea unei reţete medicul va completa câmpurile din fereastră şi va apăsa

butonul Salvează, astfel reţeta va fi salvată în baza de date. La apăsarea butonului Salvează se

apelează metoda save(Object) din ORM-ul implementat.

Secvenţa 5.1. – Salvarea unei reţete

Secvența de cod de mai sus ilustrează modul de preluare și prelucrare a datelor din

interfață și apoi salvarea lor în baza de date cu ajutorul metodei save.

La apăsarea butonului Programări medicului îi sunt afişaţi toţi pacienţii ce s-au

programat pentru o consultaţie la el. Pentru afişarea programărilor este folosită metoda

readAll() din ORM.

Mai jos este exemplificată folosirea metodei readAll și afișarea datelor preluate într-

un tabel.

1. Reteta r = new Reteta(); 2. 3. r.setIdMedic(f.getIdMedic(Long.valueOf(text4.getText())); 4. r.setJudet(text_1.getText()); 5. r.setOras(text_2.getText()); 6. r.setNumePacient(text1.getText()); 7. r.setStrada(text_3.getText()); 8. 9. r.setNrStrada(Long.valueOf(text_4.getText())); 10. r.setCetatenie(text_5.getText()); 11. r.setVarsta(Integer.parseInt(text_6.getText())); 12. r.setMedicamente(text.getText()); 13. r.setDiagnostic(text2.getText()); 14. 15. int an = data.getYear()-1900; 16. int luna = data.getMonth(); 17. int zi = data.getDay(); 18. Date date = new Date(an, luna, zi); 19. r.setData(date); 20. 21. if (button.getSelection() == true) { 22. r.setSex(button.getText()); 23. } else { 24. r.setSex(button_1.getText()); 25. } 26. r.setCompensata(btnCheck.getSelection()); 27. 28. ORMHandler h=new ORMHandler(); 29. h.save(r); 30. } 31. }

Page 41: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

41

Secvenţa 5.2. – Exemplu de folosire readAll

Fig. 5.4. – Vizualizarea programărilor

1. ORMHandler h = new ORMHandler();

2. Programare p = new Programare();

3. Functionalitate f = new Functionalitate();

4.

5. List<Programare> pr = h.readAll(p);

6.

7. if (f.verificaMedic(Long.valueOf(codIdentif.getText())) == 1) {

8. for (int i = 0; i < pr.size(); i++) {

9. String nume = f.getNumeMedic(Long.valueOf(codIdentif.getText()));

10. if (pr.get(i).getNumeMedic().equals(nume)) {

11.

12. tableItem = new TableItem(table, SWT.NONE);

13. tableItem.setText(0, pr.get(i).getNumePacient());

14. tableItem.setText(1, ""+pr.get(i).getDataProgramare());

15. tableItem.setText(2, ""+pr.get(i).getOraProgramare());

16.

17. }

18. }

19. }

Page 42: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

42

Înainte de salvarea unei reţete sau de vizualizarea programărilor un medic trebuie să

introducă un cod de indentificare , unic şi cunoscut numai de el.

La apăsarea butonului Medicină naturistă se va deschide o fereastră asemănătoare cu

cea de la Medicină de familie în care un medic naturist va putea să prescrie un remediu pentru

pacient şi va putea să vizualizeze programările. Funcţionalitatea este similară cu cea de la

Medicină de familie.

Fig. 5.5. – Medicină naturistă

La apăsarea butonului Medicină veterinară se va deschide o fereastră în care un

medic veterinar va putea să elibereze tratamente pentru animalele pe care le consultă. Aici

avem funcţionalitate de introducere în baza de date a tratamentului.

Fig. 5.6. – Medicină Veterinară

Page 43: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

43

5.3. Fereastra Farmacist

La apăsarea butonului Farmacist din fereastra principală se va deschide o fereastră în

care farmacistul are posibilitatea de a vizualiza reţetele unui pacient şi de a le printa. Printarea

se face în 2 paşi: întâi farmacistul scoate reţeta din baza de date sub forma unui fişier pdf,

după aceea fişierul pdf poate fi printat. În cadrul acestei secţiuni a aplicaţiei s-au folosit

metodele readAll şi read(Object) implementate în ORM.

Secvenţa 5.3. – Exemplu de folosire metoda read

Mai sus este ilustrat un exemplu de folosire a metodei read din sistemul ORM în

această aplicație. Este folosită pentru a afla numele medicului în funcție de id-ul acestuia. Id-

ul este salvat ca informație a unei rețete în baza de date, dar este folosit pentru a putea afla

numele medicului.

Fig 5.7. – Farmacist

Long idMedic=reteta.getIdMedic(); m.setIdMedic(idMedic); handler.read(m); numeMedic = m.getNumeMedic();

Page 44: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

44

5.4. Fereastra Pacient

La apăsarea butonului Pacient din fereastra principală se deschide o fereastră cu

ajutorul căreia un pacient îşi poate face o programare la un medic. În aceasta secţiune am

folosit din ORM-ul implementat metodele save(Object) atunci când se salvează programarea

în baza de date şi metodele readAll() şi read(Object) atunci când am verificat dacă

programarea este posibilă. Programarea este salvată în baza de date doar dacă ora din ziua

aleasă de pacient la medicul dorit de el nu este ocupată.

În cazul în care programarea nu este posibilă pacientul va primi un mesaj în care este

rugat să aleaga altă ora, în caz contrar acesta va primi un mesaj prin care va fi informat că

înregistrarea a avut loc cu succes.

Fig. 5.8. – Fereastra pentru

programare

Fig. 5.9. – Mesaj în cazul în care

programarea s-a făcut cu succes

Page 45: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

45

În această testare am încercat să folosesc tabele de dimensiuni şi tipuri de date cât

mai variate pentru a demonstra funcţionalitatea ORM-ului şi avantajele acestuia. ORM-ul a

fost testat atât pe PostgreSQL cât şi pe Microsoft SQL Server 2012 pentru a demonstra

independenţa faţă de baza de date.

Cel mai mare tabel din baza de date este cel de rețete de la medicii de familie.În

imaginile următoare voi arăta că acestea sunt de tipuri cât mai variate și că de asemena nu este

necesar ca ordinea câmpurilor din clasa ce mapează tabelul să fie aceeași cu ordinea

coloanelor din tabel.

Fig. 5.11. – Coloanele tabelului rețete

Fig. 5.10. – Mesaj în cazul în care

programarea nu este posibilă

Page 46: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

46

Fig. 5.12. – Clasa Reteta ce mapează tabelul retete

Imaginea de mai sus este de asemenea și un exemplu concret de cum se face maparea

unei clase pe un tabel. Se poate vedea că maparea se poate face atât cu adnotări cât si pe baza

numelui câmpului dacă acesta se potrivește cu numele coloanei.

De asemenea testarea s-a făcut și cu câmpul compensata adnotat cu @NotPersistent

iar programul a generat o eroare de tipul NullPointerException deoarece fiind adnotat cu

@NotPersistent era ignorat la rulare, astfel că atunci când se făcea un insert în baza de date

valoarea corespunzătoare câmpului era null și nu se putea face insert-ul.

Am ales testarea sistemului pe acest gen de aplicație deoarece este un subiect de

actualitate, dar el poate fi folosit în orice domeniu ce folosește o bază de date, deoarece face

operarea cu baza de date mult mai ușoară și poate duce la rezultate îmbunătățite în domeniul

în care este utilizat.

Page 47: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

47

6. Concluzii și Dezvoltări ulterioare

6.1. Dezvoltări ulterioare

Deși în stadiul actual al lucrării sistemul îndeplinește cerințele întotdeauna este loc

de îmbunătățiri și adăugări. Printre viitoare funcții ale sistemului ORM se pot număra:

a) Posibilitatea de a crea tabele direct, prin simpla mapare a claselor, astfel ele nu ar

mai trebui create în baza de date de către programator

b) Posibilitatea căutării după un câmp dat ca parametru sau a unei liste de câmpuri

c) Menținerea unui istoric al operațiilor efectuate pe baza de date

d) Posibilitatea mapării unei chei primare compuse

e) Crearea unei metode care căreia programatorul să îi trimită ca parametru o

interogare de orice fel, iar aceasta să întoarcă rezultatul interogării

6.2. Concluzii

Un ORM este o soluție viabilă pentru programatori atunci când doresc să îmbine

programarea orientată-obiect cu lucrul cu baze date deoarece este un sistem scalabil, rapid și

ușor de folosit.

Un astfel de sistem poate duce la creare de aplicații stabile într-un timp mult mai

scurt. De asemenea duce la scrierea unui cod uşor de întreținut și depanat deoarece reduce

cantitatea de cod și este și ușor de înțeles.

Cea mai bună metodă de mapare a obiectelor pe tabele este folosirea adnotărilor

deoarece este o metodă mai intuitivă și care nu necesită crearea unor fișiere de configurare

mari și greu de urmărit.

Pentru dezvoltarea unui sistem de mapare a obiectelor pe tabelele dintr-o bază de

date este necesară folosirea atât a API-ului de JDBC cât și a API-ului de Reflection.

Acest ORM încearcă să trateze unele probleme a căror rezolvare ar duce la o utilizare

mai ușoară și la o funcționare mai aproape de ceea ce se așteaptă un programator.

Un astfel de sistem poate fi folosit la implementarea modelului și chiar a unei părți

din controller din pattern-ul de proiectare MVC(Model-View-Controller), care este una din

cele mai utilizate metode la dezvoltarea aplicațiilor atât desktop cât și web.

Page 48: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

48

7. Bibliografie

[1] Tanasa Stefan, Andrei Stefan, Olaru Cristian, 2007. „Java de la 0 la Expert –

Ediția a II-a revizuită”. POLIROM, Iași

[2] Roland Barcia, Geoffrey Hambrick, Kyle Brown, Robert Peterson, Kulvir Singh

Bhoga. 2008. “Persistence in the Enterprise: A Guide to Persistence Technologies”. IBM

Press, Boston

[3]Jakob Jenkov. „Java Reflection Tutorial”. http://tutorials.jenkov.com/java-

reflection/index.html, accesat la data de 13.06.2013

[4]Jakob Jenkov. „Java PDF Generation with IText”.

http://tutorials.jenkov.com/java-itext/index.html, accesat la data de 23.06.2013

[5]Lars Vogel. 2010. „Creating PDF with Java and iText - Tutorial”.

http://www.vogella.com/articles/JavaPDF/article.html, accesat la date de 23.06.2013

[6]Oracle Java SE Documentation, “Annotations”.

http://docs.oracle.com/javase/6/docs/technotes/guides/language/annotations.html, accesat la

data de 28.05.2013

[8]Hibernate Documentation. 2013 „Hibernate Developer Guide”.

http://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/, accesat la data de 30.05.2013

[9] Bitcell. 2009. „Tutoriale Java”. http://www.bitcell.info/tutorial-java-introducere-

despre-platforma-t674.html, accesat a data de 29.06.2013

[10]Eclipse. 2013. „SWT – The Standard Widget Toolkit”.

http://www.eclipse.org/swt/, accesat la data de 20.06.2013

[11] Oracle FAQ’s. 2013. „JDBC”. http://www.orafaq.com/wiki/JDBC, accesat la

data de 10.06.2013

[12]Wikipedia. 2013. „Object-relational mapping”.

https://en.wikipedia.org/wiki/Object-relational_mapping, accesat la data de 26.06.2013

[13]Tutorial Debug în mediul de dezvoltare Eclipse, 2007,

http://eclipsetutorial.sourceforge.net/debugger01/lesson01.html, accesat la data de 6.06.2013

[14] Documentaţie Oracle Interface ResultSetMetadata,

http://docs.oracle.com/javase/1.5.0/docs/api/java/sql/ResultSetMetaData.html, accesat la data

de 8.06.2013

[15] Historical perspective of ORM, Kenneth Downs,2010, http://database-

programmer.blogspot.ro/2010/12/historical-perspective-of-orm-and.html , accesat la data de

23.06.2013

[15] O-R Mapping, http://encyclopedia2.thefreedictionary.com/Object-

relational+mapping, accesat la data de 23.06.2013

[16] Wikipedia, 2013, PostgreSQL, http://ro.wikipedia.org/wiki/PostgreSQL,

accesat la data de 24.03.2013

Page 49: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

49

[17] Top 5 best databases, Ramesh Natarajan, 2010,

http://www.thegeekstuff.com/2010/03/top-5-best-databases/ , accesat la data de 2.06.2013

[18] Wikipedia, 2013, Microsoft Sql Server,

http://ro.wikipedia.org/wiki/Microsoft_SQL_Server, accesat la data de 24.03.2013

[19] MSDN, 2012, Features Supported by the Editions of SQL Server 2012,

http://msdn.microsoft.com/en-us/library/cc645993(v=SQL.110).aspx, accesat la data de

24.03.2013

[20] Tutorial JVM, 2012, http://lunetistii.ro/forum/tutoriale-sofware/java-vm-virtual-

machine-t208815.html, accesat la 22.06.2013

[21] Lars Vogel 2010, Eclipse Shortcuts,

http://www.vogella.com/articles/EclipseShortcuts/article.html, accesat la data de 26.06.2013

[22]IBM, 2009, Java, JDBC and SQL Data Types,

http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/a

d/rjvjdata.htm, accesat la data de 12.06.2013

[23] Imagine, http://eofdreams.com/doctor.html , accesată la data de 18.06.2013

[24] Imagine farmacist, http://ataheri.wordpress.com/2012/10/26/c3-3-r3-reflect-in-

eportfolio-what-commitment-to-the-profession-means-personally/ , accesată la data de

18.06.2013

[25] Model reţetă naturistă, http://enoratip.ro/produse/imprimate-tipizate/retete-

medicale-bloc-3a4-100-file-offset/ , accesat la data de 18.06.2013

[26] Model reţetă medicală, http://www.gorjexclusiv.ro/exclusiv/spitalul-targu-jiu-

restant-la-retete-electronice.html , accesat la data de 18.06.2013

[27] Imagine siglă de sănătate,

http://www.infosapientia.ro/Evenimente/tabid/71/articleType/ArticleView/articleId/1280/Ziua

-mondiala-a-bolnavului-Pentru-a-iesi-din-penumbra.aspx , accesat la data ded 18.06.2013

[28] Wikipedia, 2013, JDBC,

http://en.wikipedia.org/wiki/Java_Database_Connectivity, accesat la data de 10.06.2013

[29] Documentaţie Oracle, 2013, JDBC,

http://docs.oracle.com/javase/tutorial/jdbc/basics/connecting.html, accesat la data de

10.06.2013

[30] Tutorial generare PDF, http://www.openlogic.com/wazi/bid/188064/iText-

Generate-PDFs-in-Java, accesat la data de 23.06.2013

Page 50: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

50

ANEXĂ COD

1) DataConn.java

package org.licenta.miniorm.connection;

import java.io.IOException;

import java.io.InputStream;

import java.util.Properties;

public class DataConn {

public String driverName;

public String url;

public String databaseName;

public String usrName;

public String usrPass;

private Properties getInfo() {

InputStream is = getClass().getResourceAsStream( "connection_data.properties");

Properties props = new Properties();

try {

props.load(is);

} catch (IOException e1) {

e1.printStackTrace();

}

try {

is.close();

} catch (IOException e) {

e.printStackTrace();

}

return props;

}

public DataConn() {

Properties props = getInfo();

this.databaseName = props.getProperty("databaseName");

this.driverName = props.getProperty("driver");

Page 51: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

51

this.url = props.getProperty("url");

this.usrName = props.getProperty("userName");

this.usrPass = props.getProperty("userPassword");

}

}

2) ConnectionDB.java

package org.licenta.miniorm.connection;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

public class ConnectionDB {

public DataConn data = new DataConn();

public String driverName = data.driverName;

public String url = data.url;

public String databaseName = data.databaseName;

public String usrName = data.usrName;

public String usrPass = data.usrPass;

public Connection connect() {

Connection connection = null;

System.out.println(this.driverName);

try {

Class.forName(driverName);

} catch (ClassNotFoundException e1) {

System.out.println("Problema la incarcarea driver-ului!");

}

try {

if(driverName.equals("com.microsoft.sqlserver.jdbc.SQLServerDriver")){

String con =url+";databaseName="+databaseName+";user="+usrName+";password="+usrPass;

connection = DriverManager.getConnection(con);

} else {

connection = DriverManager.getConnection(url+databaseName,usrName,usrPass);

}

Page 52: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

52

} catch (SQLException e) {

System.out.println("Conectarea nu a reusit!");

}

System.out.println("Conectarea s-a facut cu succes!");

return connection;

}

}

3)QueryActions.java

package org.licenta.miniorm.queryactions;

import java.sql.Connection;

import java.sql.Date;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import org.licenta.miniorm.connection.ConnectionDB;

/**

* @author ALIN

* Clasa pentru operatiile de lucru cu baza de date.

*/

public class QueryActions {

private String table;

public QueryActions(String table) {

this.table = table;

}

public List<String> getColumns() {

List<String> rez = new ArrayList<String>();

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

ResultSetMetaData rsmd = null;

String helpQuery = "SELECT * FROM " + this.table;

Page 53: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

53

try {

Statement helpStmt = connect.createStatement();

ResultSet helpRs = helpStmt.executeQuery(helpQuery);

rsmd = helpRs.getMetaData();

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

try {

for (int i = 1; i < rsmd.getColumnCount() + 1; i++)

rez.add(rsmd.getColumnName(i));

} catch (SQLException e) {

e.printStackTrace();

}

return rez;

}

/**

* Intoarce din baza inregistrarea cu id-ul id

* @param id

* @return

*/

public HashMap<String, Object> read(Long id) {

HashMap<String, Object> rezultat = new HashMap<String, Object>();

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

String idTabel = "";

ResultSet resultSet = null;

ResultSetMetaData rsmd = null;

String helpQuery = "SELECT * FROM " + this.table;

try {

Statement helpStmt = connect.createStatement();

ResultSet helpRs = helpStmt.executeQuery(helpQuery);

rsmd = helpRs.getMetaData();

idTabel = rsmd.getColumnName(1);

Page 54: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

54

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

String query = "SELECT * FROM " + this.table + " WHERE " + idTabel

+ "=" + id;

try {

Statement statement = connect.createStatement();

resultSet = statement.executeQuery(query);

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme cu query-ul principal!");

}

try {

Integer count = rsmd.getColumnCount();

while (resultSet.next()) {

for (int i = 1; i < count + 1; i++) {

String cheie = rsmd.getColumnName(i);

Object valoare = resultSet.getObject(rsmd.getColumnName(i));

rezultat.put(cheie, valoare);

}

}

} catch (SQLException e1) {

e1.printStackTrace();

System.out.println("Probleme la crearea hashmap-ului!");

}

try {

connect.close();

} catch (SQLException e) {

System.out.println("Problema la inchiderea conexiunii la baza!");

}

return rezultat;

}

/**

Page 55: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

55

* Intoarce din baza toate inregistrarile pentru tabel

*

* @return

*/

public List<HashMap<String, Object>> readAll() {

List<HashMap<String, Object>> rezultat = new ArrayList<HashMap<String, Object>>();

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

ResultSet resultSet = null;

ResultSetMetaData rsmd = null;

String helpQuery = "SELECT * FROM " + this.table;

try {

Statement helpStmt = connect.createStatement();

resultSet = helpStmt.executeQuery(helpQuery);

rsmd = resultSet.getMetaData();

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

try {

Integer count = rsmd.getColumnCount();

while (resultSet.next()) {

HashMap<String, Object> hash = new HashMap<String, Object>();

for (int i = 1; i < count + 1; i++) {

hash.put(rsmd.getColumnName(i),

resultSet.getObject(rsmd.getColumnName(i)));

}

rezultat.add(hash);

}

} catch (SQLException e1) {

e1.printStackTrace();

System.out.println("Probleme la crearea hashmap-ului!");

}

try {

connect.close();

} catch (SQLException e) {

System.out.println("Problema la inchiderea conexiunii la baza!");

Page 56: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

56

}

return rezultat;

}

/**

* Sterge din tabel inregistrarea cu id-ul id

*

* @param id

*/

public void delete(Long id) {

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

String idTabel = "";

ResultSetMetaData rsmd = null;

Statement stmt = null;

String helpQuery = "SELECT * FROM " + this.table;

try {

Statement helpStmt = connect.createStatement();

ResultSet helpRs = helpStmt.executeQuery(helpQuery);

rsmd = helpRs.getMetaData();

idTabel = rsmd.getColumnName(1);

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

String query = "DELETE FROM " + this.table + " WHERE " + idTabel + "="

+ id;

try {

stmt = connect.createStatement();

stmt.executeUpdate(query);

} catch (SQLException e) {

e.printStackTrace();

}

try {

connect.close();

} catch (SQLException e) {

System.out.println("Problema la inchiderea conexiunii la baza!");

Page 57: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

57

}

}

/**

* Face o inserare in baza cu valorile din lista

*

* @param lista

*/

public void insert(List<Object> lista) {

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

String help = "(";

Statement stmt = null;

ResultSet resultSet = null;

Long idRow = 0L;

String helpQuery = "SELECT * FROM " + this.table;

try {

Statement helpStmt = connect.createStatement();

resultSet = helpStmt.executeQuery(helpQuery);

while (resultSet.next()) {

Long idRow1 = resultSet.getLong(1);

if (idRow1 > idRow)

idRow = idRow1;

}

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

idRow++;

help += idRow + ", ";

for (int i = 0; i < lista.size(); i++) {

if (i < lista.size() - 1) {

if (lista.get(i).getClass().getName()

.equals("java.lang.String")) {

help += "\'" + lista.get(i) + "\', ";

} else if (lista.get(i).getClass().getName()

.equals("java.util.Date")) {

Page 58: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

58

java.sql.Date data = new Date(

((java.util.Date) lista.get(i)).getTime());

help += "\'" + data + "\', ";

} else {

help += lista.get(i) + ", ";

}

} else {

if (lista.get(i).getClass().getName()

.equals("java.lang.String")) {

help += "\'" + lista.get(i) + "\') ";

} else if (lista.get(i).getClass().getName()

.equals("java.util.Date")) {

java.sql.Date data = new Date(

((java.util.Date) lista.get(i)).getTime());

help += "\'" + data + "\') ";

} else {

help += lista.get(i) + ")";

}

}

}

String query = "INSERT INTO " + this.table + " VALUES " + help;

try {

stmt = connect.createStatement();

stmt.executeUpdate(query);

} catch (SQLException e) {

e.printStackTrace();

}

try {

connect.close();

} catch (SQLException e) {

System.out.println("Problema la inchiderea conexiunii la baza!");

}

}

/**

*

Page 59: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

59

* Updateaza in tabel cu lista de valori data, inregistrarea cu id-ul id

*

* @param id

* @param valori

*/

public void update(Long id, List<Object> valori) {

ConnectionDB conn = new ConnectionDB();

Connection connect = conn.connect();

String idTabel = "";

ResultSetMetaData rsmd = null;

String help = "UPDATE " + this.table + " SET ";

List<String> coloane = new ArrayList<String>();

String helpQuery = "SELECT * FROM " + this.table;

try {

Statement helpStmt = connect.createStatement();

ResultSet helpRs = helpStmt.executeQuery(helpQuery);

rsmd = helpRs.getMetaData();

idTabel = rsmd.getColumnName(1);

for (int i = 2; i < rsmd.getColumnCount() + 1; i++) {

coloane.add(rsmd.getColumnName(i));

}

} catch (SQLException e) {

e.printStackTrace();

System.out.println("Probleme la metadata!");

}

for (int i = 0; i < valori.size(); i++) {

if (i < valori.size() - 1) {

if (valori.get(i).getClass().getName()

.equals("java.lang.String")) {

help += coloane.get(i) + "=" + "\'" + valori.get(i)

+ "\', ";

} else if (valori.get(i).getClass().getName()

.equals("java.util.Date")) {

java.sql.Date data = new Date(

((java.util.Date) valori.get(i)).getTime());

help += coloane.get(i) + "=" + "\'" + data + "\', ";

} else {

Page 60: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

60

help += coloane.get(i) + "=" + valori.get(i) + ", ";

}

} else {

if (valori.get(i).getClass().getName()

.equals("java.lang.String")) {

help += coloane.get(i) + "=" + "\'" + valori.get(i)

+ "\' WHERE " + idTabel + "=" + id;

} else if (valori.get(i).getClass().getName()

.equals("java.util.Date")) {

java.sql.Date data = new Date(

((java.util.Date) valori.get(i)).getTime());

help += coloane.get(i) + "=" + "\'" + data + "\' WHERE "

+ idTabel + "=" + id;

} else {

help += coloane.get(i) + "=" + valori.get(i) + " WHERE "

+ idTabel + "=" + id;

}

}

}

try {

Statement stmt = connect.createStatement();

stmt.executeUpdate(help);

} catch (SQLException e) {

e.printStackTrace();

}

try {

connect.close();

} catch (SQLException e) {

System.out.println("Problema la inchiderea conexiunii la baza!");

}

}

/**

* Insereaza in baza lista de valori daca id-ul este null, iar in caz

* contrar updateaza in tabel inregistrarea cu id-ul id

*

* @param id

Page 61: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

61

* @param valori

*/

public void save(Long id, List<Object> valori) {

if (id != null)

update(id, valori);

else

insert(valori);

}

}

3) ORMHandler.java

/**

*

*/

package org.licenta.miniorm.ormhandler;

import java.lang.annotation.Annotation;

import java.lang.reflect.Field;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import org.licenta.miniorm.annotations.Column;

import org.licenta.miniorm.annotations.NotPersistent;

import org.licenta.miniorm.annotations.PK;

import org.licenta.miniorm.annotations.Table;

import org.licenta.miniorm.queryactions.QueryActions;

/**

* @author ALIN

*/

public class ORMHandler {

public ORMHandler() {

super();

}

@SuppressWarnings({ "rawtypes" })

Page 62: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

62

public <T> Long getId(T object) {

Long id = null;

Class objectClass = object.getClass();

Field[] fields = objectClass.getDeclaredFields();

for (Field field : fields) {

field.setAccessible(true);

Annotation annot = field.getAnnotation(PK.class);

if (annot instanceof PK

&& field.getType().getSimpleName().equals("Long")) {

try {

id = (Long) field.get(object);

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

return id;

}

@SuppressWarnings({ "rawtypes", "unchecked" })

public <T> String getTableName(T object) {

Class objectClass = object.getClass();

Annotation annotation = objectClass.getAnnotation(Table.class);

Table table = (Table) annotation;

String tableName = table.name();

return tableName;

}

@SuppressWarnings({ "rawtypes" })

public <T> void read(T object) {

String colName = "";

Long id = getId(object);

String tableName = getTableName(object);

Class objectClass = object.getClass();

Field[] fields = objectClass.getDeclaredFields();

Page 63: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

63

QueryActions action = new QueryActions(tableName);

HashMap<String, Object> rez = action.read(id);

for (Field field : fields) {

field.setAccessible(true);

Annotation[] annots = field.getAnnotations();

if (annots.length == 0) {

colName = field.getName();

} else {

for (Annotation a : annots) {

if (a instanceof Column) {

Column col = (Column) a;

colName = col.name();

} else if (!(a instanceof NotPersistent)) {

colName = field.getName();

}

}

}

if (rez.containsKey(colName)) {

try {

field.set(object, rez.get(colName));

} catch (IllegalArgumentException | IllegalAccessException e) {

e.printStackTrace();

}

}

}

}

@SuppressWarnings({ "rawtypes", "unchecked" })

public <T> List<T> readAll(T object) {

String colName = "";

Object inst = null;

List<T> rez = new ArrayList<T>();

List<HashMap<String, Object>> help = new ArrayList<HashMap<String, Object>>();

Class objectClass = object.getClass();

Annotation annotation = objectClass.getAnnotation(Table.class);

Table table = (Table) annotation;

String tableName = table.name();

Page 64: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

64

QueryActions action = new QueryActions(tableName);

List<String> columns = action.getColumns();

help = action.readAll();

for (int i = 0; i < help.size(); i++) {

try {

inst = object.getClass().newInstance();

} catch (InstantiationException | IllegalAccessException e) {

e.printStackTrace();

}

Class objectClass2 = inst.getClass();

Field[] fields2 = objectClass2.getDeclaredFields();

for (Field field : fields2) {

field.setAccessible(true);

Annotation[] annots = field.getAnnotations();

if (annots.length == 0) {

colName = field.getName();

System.out.println(colName);

} else {

for (Annotation a : annots) {

if (a instanceof PK

&& field.getType().getSimpleName()

.equals("Long")) {

try {

Object firstKey = columns.get(0);

field.set(inst, help.get(i).get(firstKey));

} catch (IllegalArgumentException

| IllegalAccessException e) {

e.printStackTrace();

}

}

if (a instanceof Column) {

Column col = (Column) a;

colName = col.name();

} else if (!(a instanceof NotPersistent)) {

colName = field.getName();

}

}

Page 65: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

65

}

if (help.get(i).containsKey(colName)) {

try {

field.set(inst, help.get(i).get(colName));

} catch (IllegalArgumentException | IllegalAccessException e) {

e.printStackTrace();

}

}

}

rez.add((T) inst);

}

return rez;

}

public <T> void delete(T object) {

Long id = getId(object);

String tableName = getTableName(object);

QueryActions action = new QueryActions(tableName);

action.delete(id);

}

@SuppressWarnings("rawtypes")

public <T> void save(T object) {

Long id = getId(object);

String tableName = getTableName(object);

List<Object> valori = new ArrayList<Object>();

Class objectClass = object.getClass();

String colName = "";

int pos = 0;

QueryActions action = new QueryActions(tableName);

List<String> coloane = action.getColumns();

System.out.println(coloane);

for (int i = 0; i < coloane.size() - 1; i++) {

valori.add(null);

}

Field[] fields = objectClass.getDeclaredFields();

Page 66: LUCRARE DE LICENŢĂ - acse.pub.roacse.pub.ro/wp-content/uploads/2013/07/DragomirAlin_341B1... · J2SE – Java Standard Edition MVC – Model View Controller ORM – Object Relational

66

for (Field field : fields) {

field.setAccessible(true);

Annotation[] annots = field.getAnnotations();

if (annots.length == 0) {

colName = field.getName();

pos = coloane.indexOf(colName) - 1;

} else {

for (Annotation a : annots) {

if (a instanceof Column) {

Column col = (Column) a;

colName = col.name();

pos = coloane.indexOf(colName) - 1;

} else if (!(a instanceof NotPersistent)

&& !(a instanceof PK)) {

colName = field.getName();

pos = coloane.indexOf(colName) - 1;

} else {

colName = "";

}

}

}

if (colName != "") {

try {

valori.set(pos, (Object) field.get(object));

} catch (IllegalArgumentException | IllegalAccessException e) {

e.printStackTrace();

}

}

}

action.save(id, valori);

}

}


Recommended