71
Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad 1. Uvod Većina aplikacija današnjice zahteva određenu trajnost podataka, stoga je perzistentnost jedna od fundamentalnih koncepata razvoja aplikacija. Najopštije rečeno, perzistentnost je sposobnost objekta da preživi vek trajanja procesa operativnog sistema u kome je nastao. U tu svrhu danas se najviše koriste relacione baze podataka. Relacioni model predstavlja podatke tabelama i relacijama dok za manipulaciju podacima koristi neproceduralni jezik – SQL. Obzirom da je Java objektno orijentisani programski jezik, podatke ne tretira na isti način kao što to rade relacione baze podataka. Podaci su predstavljeni kao objekti sa svojim atributima, odnosno detaljima o samom objektu. Dok objekat poseduje identitet, stanje i ponašanje pored samih podataka, relacione baze podataka skladište isključivo podatke. U skladu sa ovim različitostima, postoji očigledno nepodudaranje između objektnog modela Jave i relacionog modela baza podataka. Korišćenje JDBC API-a za premošćavanje ovih razlika može biti dobro rešenje u slučaju manjih projekata, međutim, budući da je JDBC API interfejs nižeg nivoa, on ne pruža dovoljan nivo apstrakcije relacionog modela kada su u pitanju veliki i kompleksni projekti. Sa JDBC-om, programer je obavezan da piše kod kojim će prevesti podatke relacionog modela u objektni model, odnosno polja u tabelama u atribute objekata, svaki put kada aplikacija zahteva interakciju sa bazom podataka. U slučaju izmena u tabeli ili samoj bazi podataka, neophodno je izmeniti svaku liniju koda aplikacije koja je u vezi sa izmenama. Takođe, programer je dužan da skup redova, JDBC-om dobijenih kao rezultat upita, ručno tumači, imajući na umu njihov tip i vodeći računa o konverziji SQL i Java tipova podataka. 1

Diplom Ski

Embed Size (px)

Citation preview

Page 1: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

1. UvodVećina aplikacija današnjice zahteva određenu trajnost podataka, stoga je perzistentnost jedna od fundamentalnih koncepata razvoja aplikacija.

Najopštije rečeno, perzistentnost je sposobnost objekta da preživi vek trajanja procesa operativnog sistema u kome je nastao.

U tu svrhu danas se najviše koriste relacione baze podataka.

Relacioni model predstavlja podatke tabelama i relacijama dok za manipulaciju podacima koristi neproceduralni jezik – SQL. Obzirom da je Java objektno orijentisani programski jezik, podatke ne tretira na isti način kao što to rade relacione baze podataka. Podaci su predstavljeni kao objekti sa svojim atributima, odnosno detaljima o samom objektu. Dok objekat poseduje identitet, stanje i ponašanje pored samih podataka, relacione baze podataka skladište isključivo podatke. U skladu sa ovim različitostima, postoji očigledno nepodudaranje između objektnog modela Jave i relacionog modela baza podataka.

Korišćenje JDBC API-a za premošćavanje ovih razlika može biti dobro rešenje u slučaju manjih projekata, međutim, budući da je JDBC API interfejs nižeg nivoa, on ne pruža dovoljan nivo apstrakcije relacionog modela kada su u pitanju veliki i kompleksni projekti. Sa JDBC-om, programer je obavezan da piše kod kojim će prevesti podatke relacionog modela u objektni model, odnosno polja u tabelama u atribute objekata, svaki put kada aplikacija zahteva interakciju sa bazom podataka. U slučaju izmena u tabeli ili samoj bazi podataka, neophodno je izmeniti svaku liniju koda aplikacije koja je u vezi sa izmenama. Takođe, programer je dužan da skup redova, JDBC-om dobijenih kao rezultat upita, ručno tumači, imajući na umu njihov tip i vodeći računa o konverziji SQL i Java tipova podataka.

Praktičnije i efikasnije rešenje koje se nameće jeste okvir koji će se ponašati kao posrednik između objektnog i relacionog sveta.

Proces transformacije relacione paradigme u objektnu poznat je kao objektno-relaciono preslikavanje – ORM (Object Relational Mapping) I ono je upravo prikazano u ovom radu.

U prvom delu rada prikazano je objektno-relaciono preslikavanje uopšte.

U drugom delu opisana je JPA specifikacija kao realizacija objektno-relacionog preslikavanja u Java okruženju.

U trećem delu predstavljena je Hibernate tehnologija kao jedna od implementacija JPA specifikacije.

U poslednjem delu dat je primer iz prakse gde je deo informacionog sistema najpre projektovan standardnim metodama, a zatim i izvršena njegova implementacija koja je priložena uz ovaj rad.

1

Page 2: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

2. Object Relational Mapping - ORMORM predstavlja mehanizam za transformisanje podataka iz objektnog u relacioni model i obratno. Tačnije, ORM predstavlja proces perzistencije objekata u relacionu bazu podataka i obratno, proces preuzimanja podataka iz relacione baze podataka i pakovanja u objekte. Transformisanje podataka se vrši u perzistentnom sloju.

Razvojni tim raspolaže sa više mogućnosti implementacije ovog mehanizma. ORM se može implementirati samo pomoću SQL-a i JDBC-a ili razvojni tim može koristiti alat koji ovaj proces automatizuje. Alati koji automatizuju ovaj proces se nazivaju ORM alati. [1]

2.1 ORM alati

ORM alati vrše automatsko mapiranje na osnovu konfiguracionih fajlova – najčešće XML dokumenata. Konfiguracija mapiranja se vrši samo na jednom mestu, a u slučaju eventualnih izmena menja se samo konfiguracioni fajl. Kada je potrebno perzistirati neki Java objekat, ORM alat će generisati potreban SQL kod u pozadini na osnovu mapiranja. ORM komponenta sistema se, u cilju većeg nivoa apstrakcije, postavlja iznad JDBC API-a, oslobađajući na taj način programera detalja vezanih za konekciju i tumačenje relacionih podataka. Konfiguracioni parametri se unose jednom, a zatim ORM alat vrši automatsko povezivanje i mapiranje kada je potrebna interakcija sa bazom, isporučujući programeru uvek čiste Java objekte.

Danas postoji veliki broj ORM alata, uključujući besplatne i komercijalne, Java ili .NET orijentisane. Najpoznatiji od njih su:

Oracle TopLink 1- obezbeđuje efikasan mehanizam za skladištenje Java objekata i EJB komponenti u relacionim bazama podataka, kao i mehanizam za konverziju između Java objekata i XML dokumenata (JAXB - Java Architecture for XML Binding ). TopLink je originalno razvijen 1990.godine od strane The Object People, a 2002. godine ga je preuzeo Oracle. Aktuelna verzija je Oracle TopLink 12c i besplatna je za preuzimanje.

Hibernate2 - predstavlja ORM alat koji obezbeđuje servis za objektno/relacionu perzistenciju, kao i upitne servise. Razvijen je od strane JBoss-a, predstavlja projekat otvorenog koda (open source) i besplatan je za korišćenje. Aktuelna verzija je Hibernate 4.0.1 , a postoji i verzija NHibernate, za .NET Framework - NHibernate 3.2.0.

iBATIS3 - okvir za mapiranje podataka koji olakšava korišćenje relacionih baza podataka od strane Java i .NET aplikacija, korišćenjem XML deskriptora. Razvijen je od strane Apache organizacije.

JDO (Java Data Objects)4 - predstavlja prvu specifikaciju za perzistenciju Java objekata razvijenu od strane Sun Microsystems-a 2002. godine, verzija JDO 1. Postoje brojne implementacije JDO specifikacije, uključujući otvorena i komercijalna rešenja. Neke od njih su: JPOX(JDO 2 implementacija otvorenog koda), Eclipse JSR 220 ORM alat (implementacija EJB 3 i JDO 2 standarda), Signsoft (intelliBO), BEA (Kodo JDO).

1 Oracle Toplink - http://www.oracle.com/technology/products/ias/toplink/index.html2 Hibernate - http://www.hibernate.org3 iBATIS - http://www.mybatis.org/4 JDO API - http://java.sun.com/products/jdo/

2

Page 3: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

JPA (Java Persistance API) - naslednik JDO API-a i deo je trenutno aktuelnog rešenja za distribuirano programiranje u Java okruženju zvanom EJB 3 (Enterprise JavaBeans version 3). Zasnovan je na idejama koje su doneli pomenuti projekti TopLink, Hibernate, iBATIS i sam JDO.

2.2 ORM podsistem

ORM podsistem se tipično sastoji iz tri glavna sloja: objektnog, sloja za pristup podacima i međusloja za mapiranje.

Objektni sloj ima interfejse slične kao u slučaju objektno orijentisanih baza podataka, u cilju veće udobnosti i prirodnijeg korišćenja objektno orijentisanih jezika za manipulaciju i čuvanje podataka. U cilju enkapsulacije objektnog koncepta, funkcije objektnog sloja su sledeće: kompleksni objekti, identitet objekta, enkapsulacija, tipovi i klase, hijerarhija klasa i tipova, kasno povezivanje i upitni interfejs.

Objektni sloj koristi sloj za pristup podacima kao interfejs ka relacionoj bazi podataka ili XML dokumentima. Funkcije sloja za pristup podacima su: perzistencija podataka, konkurentnost, upitni interfejs, oporavak od grešaka. Na ovom sloju, apstrakcije poput kompleksnih tipova podataka (na primer, grupisanje logički povezanih podataka), nasleđivanja i veza su nevidljive, i one moraju biti implementirane od strane objektnog sloja. Sloj za pristup podacima šalje ili prihvata podatke do, odnosno od relacione baze (najčešće posredstvom JDBC API-a, kao industrijskog i opšte prihvaćenog standarda) ili XML dokumenata (putem DOM API-a5).

Međusloj za mapiranje na osnovu parametara iz konfiguracionog fajla omogućava prevođenje podataka između relacionog ili hijerarhijskog modela i objektnog.

Na slici 1 su prikazana rešenja sa i bez ORM podsistema. Simbolički je prikazano kako ORM sloj programeru pruža viši nivo apstrakcije, oslobađajući ga tako potrebe da tokom pisanja koda uvek vodi računa o različitim paradigmama.

Obzirom da Java jezik po svojoj prirodi pripada objektnom domenu, korišćenjem ORM-a gubi se neophodnost prevođenja jer se, sa stanovišta programera, ostaje u istom modelu.

5 Document Object Model API - http://www.w3.org/DOM/

3

Page 4: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Slika 1: Arhitekture sa i bez ORM sistema [6]

2.3 ORM nivoi kvaliteta

Postoje četiri nivoa ORM kvaliteta [5]:

1. Čisto relacioni – Cela aplikacija, kao i korisnički interfejs je dizajnirana na osnovu relacionog modela i SQL relacionih operacija. Ovaj pristup može biti odlično rešenje za jednostavne aplikacije gde se mali nivo ponovnog korišćenja koda toleriše. Direktan SQL može biti fino podešen, ali nedostaci, kao što su portabilnost i održavanje, su veoma veliki pogotovu na duži period. Ova kategorija aplikacija masovno koristi uskladištene procedure, prebacujući deo posla iz poslovnog sloja u bazu. Zbog ovakvih nedostataka ovaj pristup nema primenu u velikim sistemima.

2. Slabo objektno mapiranje – Entiteti su predstavljeni klasama i preslikavaju se ručno u relacione tabele. Ručno pisani SQL/JDBC kod je sakriven od poslovnog sloja koristeći dizajn paterne. Ovaj pristup je široko rasprostranjen i uspešan za aplikacije sa malim brojem entiteta ili za aplikacije sa izgenerisanim modelima podataka koji su nastali na osnovu meta podataka. Ovde je takođe moguće korišćenje uskladištenih procedura.

3. Srednje objektno mapiranje – Aplikacija je dizajnirana koristeći objektni model. SQL je izgenerisan u vreme pravljenja aplikacije koristeći alat za generisanje upita ili u vreme izvršenja aplikacije od strane perzistentnog okvira, koji se koristi u razvoju aplikacije. Asocijacije između objekata su podržane mehanizmom za perzistenciju, a upiti mogu biti konstruisani objektno-orjentisanim jezikom za kreiranje upita (object-oriented expression language). Objekti se čuvaju u perzistentnom sloju. Veliki broj ORM proizvoda podržava makar ovaj nivo funkcionalnosti. Ovo mapiranje je pogodno za srednje aplikacije sa kompleksnim transakcijama, delom i kada je portabilnost između različitih sistema za upravljanje bazama podataka od značaja. Ove aplikacije uglavnom ne koriste uskladištene procedure.

4

Page 5: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

4. Potpuno objektno mapiranje – Potpuno objektno mapiranje podržava sofisticirano modelovanje: kompozicija, nasleđivanje, polimorfizam. Perzistentni sloj implementira transparentnu perzistentnost. Perzistentne klase ne nasleđuju neku osnovnu klasu niti su obavezne da implementiraju neki interfejs. Efikasne strategije povezivanja (kasno i potpuno povezivanje) i strategije snimanja su implementirane transparentno u aplikaciji. Ovaj nivo funkcionalnosti ne može baš lako biti obezbeđen korisničkim perzistentnim slojem (potrebni su meseci i godine razvoja). Veliki broj komercijalnih i open source Java ORM alata je ispunio ovaj nivo kvaliteta.

2.4 Prednosti ORM-a

U ovom poglavlju su ukratko navedene prednosti korišćenja ORM-a i ORM alata [5]: Produktivnost – Kod koji se odnosi na perzstenciju podataka se ponekad smatra šablonskim kodom u Java aplikaciji. ORM alat eliminiše osnovni deo posla i ostavlja vreme programerima da se koncentrišu na poslovne probleme aplikacije. Nije bitno koja se strategija razvoja aplikacije preferira, od vrha ka dnu, gde se počinje sa izradom domenskih objekata, ili od dna ka vrhu, gde se počinje sa postojećom šemom baze podataka ORM alat značajno smanjuje vreme razvoja. Održavanje – Automatizovana objektno-relaciona perzistentnost bitno smanjuje broj linija koda. Naravno, pitanje je koliko je ispravno meriti kompleksnost aplikacije kroz broj linija koda. U sistemu sa ručno pisanim slojem za perzistenciju uvek postoji velika povezanost relacione reprezentacije podataka i objektnog modela podataka, menjanje jednog automatski povlači i menjanje drugog i obrnuto. Često se dešava da dizajn jedne prezentacije podataka iziskuje promenu druge. Uglavnom se dešava da promena dizajna relacione prezentacije ugrožava promenu domenskog modela. ORM pruža među sloj između dva modela i tako na najveći mogući način izoluje svaki model sa minimalnim promenama kod drugog. Performanse – Softverski inženjeri se uglavnom žale na loše performanse ovog rešenja. Ručno pisan kod za perzistenciju je uglavnom brži od automatizovane perzistencije. To je tačno. Međutim, isto tako važi da se Assembly kod uvek brže izvršava od Java koda. Kada govorimo o performansama, tu ne utiče samo brzina izvršavanja koda. Za ručno pisan kod je uvek potrebno mnogo više vremena od automatski izgenerisanog koda.

Nezavisnost od proizvođača – ORM izdvaja aplikaciju od relacione baze podataka i SQL dijalekta. ORM alati podržavaju veći broj baza podataka pa Java aplikacija koja ga koristi ima visok nivo portabilnosti. Ne može se u potpunosti očekivati potpunu portabilnost zato što se mogućnosti baza podataka razlikuju. Postizanje potpune portabilnosti bi žrtvovalo prednosti nekih moćnih platformi. Obično je jednostavnije razvijati više platformske (cross-platform) aplikacije koje koriste ORM.

3. Java Persistance API - JPA

JPA specifikacija je deo JSR-220 specifikacije pod upravom Java Community Process Program nastala kao rezultat udruženog rada članova JSR 220 Expert Group koju čine najpoznatije kompanije iz oblasti razvoja softvera i predstavlja okvir koji nam pomaže u

5

Page 6: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

radu sa relacionima bazama podataka tako što služi kao okvir za preslikavanje podataka i struktura između podataka koji se čuvaju u relacionoj bazi podataka u objekte objektno orjentisanog okruženja kao što je Java. Sledi prikaz osnovnih komponenti JPA standarda.

Slika 2: Entiteti JPA API-ja [4]

3.1. Entiteti

Entiteti predstavljaju perzistentne objekte koji ne nestaju po završetku komunikacije sa klijentom, jednim ili više njih. Životni vek im je vezan za životni vek podataka koji predstavljaju, a ne aplikacije koja ih koristi. Njima su tipično predstavljeni podaci uskladišteni u jednom redu tabele u bazi podataka. Na ovaj način podatke možemo čuvati i kasnije ponovo koristiti.

Za razliku od objekata koje moramo “ručno” čuvati J2EE nudi Java Persistence API (JPA) koji nam nudi okvir (framework) za rad sa entity bean-ovima. Ovaj okvir specificira API preko koga možemo izvršavati upite, čitati, pisati, brisati podatke, a sve u duhu potpuno objektno orjentisanog programiranja, bez obzira na način i mesto gde se podaci skladište.

Svi podaci se jedinstveno identifikuju preko id objekta. Entity bean može upravljati svojim stanjem “ručno” ili može ovaj deo prepustiti samom kontejneru:

6

Page 7: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Bean-managed persistence - Sam programer piše kod za perzistentnost podataka i brine se o svim aspektima upravljanja slojem skladištenja podataka.

Container-managed persistence - Programer definiše polja koja će biti perzistentna, a zatim koristi servise kontejnera za ostvarenje funkcionalnosti u vezi sa perzistencijom objekata. Ovi binovi su prenosiviji (portabilniji) jer ostavljamo u nadležnost kontejnera sve funkcionalnosti koje implementiraju komunikaciju sa slojem pristupa sistemima za upravljanje bazom podataka.

Uslovi koje Entity klase moraju ispunjavati su sledeći: Entity klasa mora imati ili anotaciju Entity ili odgovarajući XML deskriptor. Public ili protected konstruktor bez argumenata. Entity klasa mora biti top-level klasa. Entity klasa ne sme biti final. Entity klasa bi trebala da implementira Seralizable interface ako će se objekat slati

iz jedne u drugu JVM. Entiteti podržavaju nasleđivanje, polimorfizam, asocijacije kao i polimorfne upite.

3.1.1 Relacije između entiteta

Entiteti između sebe ostvaruju relacije koje predstavljaju način komunikacije između dva entiteta. Oni mogu biti svesni postojanja veze ka drugom entitetu, a mogu biti deo te veze tako što samo primaju poruke od drugog entiteta ali ne mogu i oni poslati poruku drugom entitetu.

Postoje dva tipa relacija: Jednosmerne veze - predstavljaju relacije između entiteta u kome jedna strana

sadrži i/ili poziva metode drugog entiteta, dok taj drugi entitet ne zna za prvi entitet. Dvosmerne veze - predstavljaju veze u kojima su obe strane svesne postojanja

druge strane u relaciji tj. jedan entitet koristi metode ili atribute drugog entiteta i obratno.

3.1.1.1 Jednosmerne relacije

Jednosmerna relacija 1->1

Slika 3: Jednosmerna relacija jedan-prema-jedan

Entitet A referencira jedno pojavljivanje entiteta B. Entitet B ne referencira entitet A.

Jednosmerna veza ima samo jednu stranu koja može biti vlasnik relacije (entitet A). U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko spoljnog ključa na vlasničkoj strani (polja u tabeli A).

7

Page 8: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Jednosmerna relacija 1->*

Slika 4: Jednosmerna relacija jedan-prema-više

Entitet A referencira kolekciju entiteta B. Entitet B ne referencira entitet A.

Jednosmerna veza ima samo jednu potencijalnu stranu koja može biti vlasnik relacije, entitet A. Razlog je taj što je samo entitet A svestan postojanja relacije između entiteta A i B tako da je on jedina strana koja može održavati konzistentnost relacije između njih. U memoriji to se radi tako što ima referencu na objekat entiteta B, a u bazi podataka preko vezne tabele koju će da ažurira entitet A. U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko treće (JOIN) tabele.

Jednosmerna relacija *->1

Slika 5: Jednosmerna relacija više-prema-jedan

Kolekcija entiteta A referencira jedno pojavljivanje entiteta B. Entitet B ne referencira entitet A.

Jednosmerna veza ima samo jednu stranu koja može biti vlasnik relacije, entitet A. U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko spoljnog ključa na vlasničkoj strani (tabeli A).

8

Page 9: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Jednosmerna relacija *->*

Slika 6: Jednosmerna relacija više-prema-više

Kolekcija entiteta A referencira kolekciju pojavljivanja entiteta B. Entitet B ne referencira kolekciju entiteta A.

Relacije od entiteta A ka entitetu B prikazuju se usmerenom strelicom, dok se relacija od entiteta B ka entitetu A prikazuje neusmerenom strelicom. Time se pokazaje da relacija od entiteta B ka entitetu A predstavlja samo logičku relaciju tj. u entitetu B ne postoji kolekcija entiteta A, ali na logičkom nivou posmatranja ova relacija ipak postoji. Jednosmerna veza ima samo jednu stranu koja može biti vlasnik relacije (entitet A). U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko treće (JOIN) tabele.

3.1.1.2 Dvosmerne relacije

Dvosmerna relacija 1->1

Slika 7: Dvosmerna relacija jedan-prema-jedan

Entitet A referencira jedno pojavljivanje entiteta B. Entitet B takođe referencira entitet A.

U dvosmernoj vezi jedan-prema-jedan svejedno je koji će entitet biti vlasnik relacije, neka bude entitet A. U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko spoljnog ključa na vlasničkoj strain (tabeli A).

Dvosmerna relacija 1->*

9

Page 10: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Slika 8 : Dvosmerna relacija jedan-prema-više

Kada je u pitanju dvosmerna relacija ova veza ima i vlasničku i inverznu stranu. Pravilo je da je vlasnik relacije uvek ona strana koja ima više-na-jedan preslikavanje. Suprotna strana je inverzna strana.

Entitet A referencira kolekciju entiteta B. Kolekcija entiteta B takođe referencira entitet A.

U relacionoj bazi entitet A se preslikava u tabelu A, entitet B u tabelu B, a veza se ostvaruje preko spoljnog ključa vlasničke strane (tabele B). Kao i u prethodnim slučajevima vlasnička strana će uvek biti ona na kojoj se nalazi više-prema-jedan strana preslikavanja iz razloga što ona ima spoljni ključ i zadužena je za održavanje konzistentnosti relacije između njih.

Dvosmerna relacija *->*

Slika 9: Dvosmerna relacija više-prema-više

Kada je u pitanju dvosmerna relacija ova veza ima i vlasničku i inverznu stranu. Kolekcija entiteta A referencira kolekciju entiteta B. Kolekcija entiteta B takođe referencira kolekciju entiteta A.

U relacionoj bazi entitet A se preslikava u tabelu A, entitet B tabelu B, a veza se ostvaruje preko treće (JOIN) tabele.

3.1.2 Strategije ostvarivanja polimorfizma u relacionim bazama podataka

Preslikavanje hijerarhije klasa definiše se preko meta podataka. Postoje tri strategije za preslikavanje hijerarhije klasa u relacionu bazu:

Strategija jedne tabele po hijerarhiji klasa - sve klase iz hijerarhije preslikavaju u jednu tabelu koja se sastoji od kolona svih polja iz hijerarhije klasa. Tabela ima kolonu koja se ponaša kao diskriminaciona i koja omogućava razgraničenje koji

10

Page 11: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

slog pripada kojoj tabeli (klasi). Ova strategija preslikavanja pruža dobru podršku za polimorfne relacije između entiteta . Nedostatak je taj što sva polja moraju biti null tj. polja specifičnih podklasa moraju moraju imati mogućnost da se u njih upisuji null vrednosti iako bi ta polja možda trebala biti ne null polja.

Strategija tabele po svakoj konkretnoj klasi - svaka klasa je preslikana u posebnu tabelu. Sva polja klase uključujući i nasleđena polja su mapirana u tabelu. Nedostaci ove strategjje su slaba podrška polimorfnim relacijama kao i upotreba SQL UNION upita (ili odvojenih SQL upita po klasama) za dobijanje podataka koji figurišu nad hijerarhijom klasa.

Strategija u kojoj postoji tabela sa poljima koja su zajednička za sve podklase i posebne tabele za svaku podklasu koje sadrže polja koja su specifična za nju - nadklasa je predstavljena svojom tabelom sa svim poljima koji su zajednički za sve podklase dok je svaka podklasa predstavljena samo podacima koji su specifični za tu podklasu. Ova strategija omogućava podršku polimorfnim relacijama. Nedostatak je korišćenje spajanja tabela kako bi se dobila odgovarajuća podklasa. Upiti koji operišu nad hijerarhijom klasa takođe zahtevaju spajanje.

3.1.3 Metapodaci

Svakom entitetu su pridruženi metapodaci u određenoj količini koji ga opisuju. Ovi metapodaci omogućuju sloju za perzistenciju da prepozna, interpretira i upravlja na odgovarajući način entitetom od učitavanja, preko izvršavanja do uklanjanja. Količina metapodataka koji su zaista neophodni da bi se opisao entitet je zapravo mala, međutim, kao i u svim sofisticiranim tehnologijama metapodacima je moguće specificirati sve relevantne detalje.

Metapodaci entiteta mogu biti specificirani na jedan od tri načina : pomoću XML deskriptora, XDoclet komentara, pomoću anotacija.

Uprkos razlikama u sintaksi moguće je svakim od navedenih pristupa postići isti nivo konfiguracije.

3.1.3.1 Anotacije

Anotacije predstavljaju osobinu programskog jezika koja omogućava struktuiranim i tipiziranim metapodacima da budu deo izvornog koda. Pojam anotacija uveden je u Java SE 5, i predstavlja ključni deo EJB 3.0 i Java EE 5 specifikacija. One se mogu koristiti kao alternativa standardnim XML deskriptor fajlovima, ili u kombinaciji sa njima.

Definicije metapodatka unutar Java koda upotrebljavaju se, u različitim oblicima, od samog nastanka Java jezika. Prvi primer bili su Javadoc tagovi u okviru komentara koji su se koristili za generisanje API dokumentacije u HTML formatu. Ideja je bila da se metapodaci nalaze u specijalnom obliku komentara unutar koda, koje zatim posebni kompajleri ili nezavisni alati obrađuju i upravljaju dobijenim informacijama. Najistaknutiji predstavnik ove tehnike jeste popularni XDoclet alat, koji je zapravo pretprocesor izvornog koda.

11

Page 12: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Bitno je istaći da su u okviru Javadoc/XDoclet pristupa metapodaci smešteni unutar komentara, što znači da ih ne obrađuje Java kompajler. Metapodaci se ne kompajliraju u regularnu klasu i dostupni su samo u vreme kompajliranja. Sintaksa i semantika metapodataka se ne proverava od strane kompajlera, što može uzrokovati kasno otkrivanje grešaka.

Za razliku od starog načina definisanja metapodatka unutar koda aplikacije, anotacije su sada deo Java jezika, a proveru sintakse i semantike, kao i kompajliranje obavlja standardni Java kompajler. Anotacije se razlikuju od ostatka programskog koda time što ispred same anotacije postoji znak “@“. Postoji veliki broj anotacija definisanih specifikacijom, a navedene su samo neke koje se često koriste u radu sa EJB komponentama [1]:

@Stateless, @Stateful, @Entity, @MessageDriven – specificiranje tipa klase,

@Local, @Remote – specificiranje tipa interfejsa, @Interceptors – definisanje svih callback klasa koje će se primenjivati nad

bean-om, @PrePassivate, @PostActivate,... – označavanje callback metode pri

prelasku iz jednog stanja u drugo, @PersistenceContext – ukazuje na zavisnost od konteksta perzistencije, @Table – navođenje primarne tabele entiteta; dodatne tabele se mogu

specificirati pomoću @SecondaryTable ili @SecondaryTables anotacija, @Column – specificiranje mapirane kolone za perzistentan atribut entiteta; moguće

je dodatno definisati i ograničenja kolone (constraints), dozvolu null vrednosti kolone, dužinu kolone itd,

@Id – specificiranje atributa koji predstavlja primarni ključ, @JoinTable – definisanje vezivne tabele u relacijama tipa više-više, @ManyToOne, @OneToOne, @OneToMany, @ManyToMany – definisanje

relacija, uz moguće navođenje dodatnih opcija kao što je na primer kaskadno brisanje.

3.2 EntityManager

EntityManager interfejs definiše metode koje služe za interakciju sa skupom perzistentnih pojavljivanja u kome se perzistentna instanca dobija pomoću jedinstvenog identifikatora instance (perzistentnim kontekstom). [6]

EntityManager API se koristi za pretraživanje instanci prema jedinstvenom identifikatoru, pravljanje upita, kreiranje i brisanje perzistentnih instanci.

Perzistentne entitete sa kojima možemo raditi preko EntityManager instance definišemo u persistence unit koja predstavlja skup entiteta koji su prema nekom kriterijumu grupisani u jednu jedinicu i koji moraju biti preslikani u istu bazu podataka.

public interface EntityManager {

public void persist(Object entity);

12

Page 13: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

public <T> T merge(T entity);

public void remove(Object entity);

public <T> T find(Class<T> entityClass, Object primaryKey);

public <T> T getReference(Class<T> entityClass, Object primaryKey);

public void flush();

public void setFlushMode(FlushModeType flushMode);

public FlushModeType getFlushMode();

public void lock(Object entity, LockModeType lockMode);

public void refresh(Object entity);

public void clear();

public boolean contains(Object entity);

public Query createQuery(String ejbqlString);

public Query createNamedQuery(String name);

public Query createNativeQuery(String sqlString, Class result- Class);

public Query createNativeQuery(String sqlString, String result-SetMapping);

public void close();

public boolean isOpen();

public EntityTransaction getTransaction(); }

Interfejs EntityManager obezbeđuje metode za tri tipa operacija: upravljanje životnim ciklusom entiteta, sinhronizacija sa bazom podataka, pretraga entiteta i izvršavanje upita.

3.2.1 Upravljanje životnim ciklusom entiteta

13

Page 14: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Životni ciklus jedne instance entiteta određen je sa dva glavna aspekta koji se odnose na vezu instance sa specifičnim kontekstom perzistencije, i sinhronizaciju stanja instance sa stanjem u bazi podataka. Menadžer entiteta razlikuje četiri stanja u životnom ciklusu entiteta:

Nova instanca (New) - Instanca entiteta je kreirana u memoriji ali joj još uvek nije dodeljen identifikator ili kontekst perzistencije. U ovom trenutku stanje entiteta još uvek nije sinhronizovano sa stanjem u bazi i menadžer ne zna za postojanje novog entiteta.

Upravljana instanca (Managed) - Entitet poseduje identifikator i kontekst perzistencije. Promene na entitetu će biti sinhronizovane sa bazom kada se transakcija uspešno izvrši (commited) ili u slučaju eksplicitno zahtevane sinhronizacije pomoću flush() operacije. Entitet dolazi u upravljano stanje na mnogo načina: pozivima persist(), merge() ili refresh() metoda, kao i u slučaju da je entitet rezultat pretrage ili upita.

Neupravljana instanca (Detached) - Entitet i dalje poseduje identifikator ali nije više asociran sa kontekstom perzistencije i menadžer više njim ne upravlja.

Uklonjena instanca (Removed) - Entitet je još uvek vezan za kontekst perzistencije ali je raspoređen za uklanjanje iz baze podataka.

Slika 10: Tranzicije stanja entiteta [6]

Operacijom remove() mogu se rasporediti za uklanjanje iz baze podataka jedino entiteti koji se nalaze u upravljanom stanju. Pomoću ove operacije podaci u bazi se raspoređuju za uklanjanje, što će se zaista i desiti kada se transakcija uspešno izvrši, ili kada se pozove operacija flush().

Pomoću operacije merge() moguće je neupravljanim entitetima ponovo dodeliti kontekst perzistencije. Entitet dolazi u Detached stanje po prestanku postojanja konteksta perzistencije ili kada se isporuči klijentu kao serijalizovan objekat.

3.2.2 Sinhronizacija sa bazom podataka

14

Page 15: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Izmene na lokalnim entitetima se obično sinhronizuju sa bazom podataka u vreme potvrđivanja transakcije (commit). Međutim, ponekad je važno izvršiti sinhronizaciju pre potvrđivanja operacija transakcije. Na primer, izmene entiteta mogu uticati na rezultate upita u okviru iste transakcije. U tom slučaju, neophodno je obaviti sinhronizaciju pre izvršavanja upita.

Izvršavanje prevremene sinhronizacije kontroliše se postavljanjem flush režima rada za željene metode korišćenjem anotacija, ili globalno za kontekst perzistencije pomoću setFlushMode() operacije. Dostupne opcije vezane za flush režim rada uključuju COMMIT za sinhronizaciju samo u vreme potvrđivanja transakcije, i AUTO za sinhronizaciju stanja entiteta i u vreme potvrđivanja transakcije i pre izvršavanja upita.

Operacija flush() obavlja sinhronizaciju stanja svih entiteta u okviru konteksta perzistencije sa entitetima u bazi ali ne uključuje i ažuriranje lokalnih entiteta na osnovu njihovog stanja u bazi. Za potrebe ažuriranja, mora se eksplicitno pozvati operacija refresh().

Dvosmerne relacije između upravljanih entiteta će postati perzistentne na osnovu referenci koje se nalaze u entitetima koji predstavljanju vlasnike relacija. Odgovornost programera je da održava relacije između entiteta na ispravan način. U slučaju jednosmerne jedan-prema-jedan i jedan-prema-više relacije odgovornost programera je da osigura postojanje odgovarajuće logike relacija. Posebno je bitno osigurati tačnost relacija između entita u smislu da promene u relacijama na entitetu koji nije vlasnik relacije treba da se reflektuju na entitet koji je vlasnik relacije. Time neće biti izgubljeni podaci u fazi sinhronizacije sa bazom podataka. Nasuprot promena na strani koja nije vlasnik relacije, pri promeni relacija na strani entiteta koji je vlasnik relacije programer može osigurati tačnost relacija i na inverznoj strani ili se može osloniti na mehanizam out-of-date references.

3.2.3 Pretraga entiteta i izvršavanje upita

U cilju identifikacije entiteta koje prethodi referenciranju instance istog, potrebno je ili direktno adresirati individualan entitet korišćenjem primarnog ključa, ili izvršiti upit koji će kao rezultat vratiti set entiteta na osnovu zadatih uslova.

Menadžer entiteta obezbeđuje metodu find() za potrebe adresiranja entiteta na osnovu primarnog ključa. Ova metoda će kao rezultat vratiti upravljan entitet odgovarajuće klase u slučaju ispravno navedenog identifikatora, u suprotnom, rezultat će biti null vrednost. U većini slučajeva identifikator entiteta nam je nepoznat, ili nam je potrebno više od jednog rezultata, ili je neophodno postaviti jedan ili više uslova za pronalaženje entiteta.

Postoje brojni način za definisanje pretrage koje nudi interfejs EntityManager, ali su generalni koraci pri tom uvek isti:

pravljenje nove javax.persistance.Query instance od strane menadžera,

postavljanje parametara upita i gornju granicu veličine rezultujećeg seta (ako je potrebno),

15

Page 16: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

izvršavanje upita.

3.3 Persistence Context

Perzistentni kontekst predstavlja skup (keš) upravljanih entitetskih instanci koje imaju svoj jedinstveni identifikator i unutar kog su entitetske instance i njihov životni ciklus kontrolisani od strane EntityManager-a. [6]

U Java EE okruženju JTA transakcija može da obuhvata pozive metoda iz nekoliko komponenti gde te komponente imaju potrebu da pristupe istom perzistencionom kontekstu unutar iste transakcije. EntityManager automatski propagira persistence context unutar iste JTA transakcije na sve komponente tako da EntityManager u njima referencira na isti persistence context. Ovakav način propagiranja context-a u Java EE container-u omogućava da aplikacija ne mora da šalje referencu na EntityManager pojavljivanje iz jedne komponente u drugu. Za EntityManager kod koga kontejner upravlja persistence context-om na ovakav način, kažemo da se on naziva kontejnerski upravljan (container-managed) EntityManager. Životni ciklus kontejnerski upravljanog (container-managed) EntityManager-a je upravljan od strane Java EE kontejnera..

U ređe korišćenim slučajevima unutar Java EE kontejnera, aplikacijama je potreban pristup persistence context-u koji nije propagiran sa JTA transakcijom preko EntityManager reference za dati persistence unit. Ovakvi slučajevi su podržani preko createEntityManager metode EntityManagerFactory interface-a. EntityManager koji se koristi u aplikaciji za kreiranje i uništavanje persistence context-a na ovakav način nazivaju se application-managed EntityManager. Životni ciklus application-managed entity manager je upravljan od strane aplikacije.

Oba pristupa, i container-managed i application-managed EntityManagers moraju biti implementirana u Java EE Web i EJB kontejnerima. Unutar EJB okruženja, najčešće se koriste container-managed entitetski menadžeri.

U Java SE okruženju, zahteva se implementacija samo application-managed načina upravljanja EntityManager-om.

Životni vek perzistencionog konteksta može biti povezan sa životnim vekom trajanja transakcije (Transaction-scoped persistence context), ili proširenim životnim vekom jedne transakcije (extended persistence context).

Podrazmevani (default) životni vek perzistentnog konteksta odgovara životnom veku transakcije. KlasaPersistenceContextType se definiše pri kreiranju instance EntityManager (bilo eksplicitno, ili preko ubacivanja (injection) ili preko JNDI lookup mehanizma).

3.3.1 Transaction-scoped Persistence Context

Životni vek Transaction-scoped perzistencionog konteksta započinje kreiranjem transakcije u okviru EntityManager instance. PersistenceContext se završava sa završetkom Transaction objekta (bilo preko commit ili rollback).

16

Page 17: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

3.3.2 Extended Persistence Context

Perzistencioni kontekst može biti održavan između više transakcija definisanjem perzistencionog konteksta kao proširenog. Kada se koristi prošireni perzistencioni kontekst onda kontekst postoji tokom čitavog trajanja EntityManager instance, sve dok se instanca ne zatvori. Perzistencioni kontekst traje tokom korišćenja više kako transakcionih tako i netransakcionih poziva nad instancom EntityManager. EntityManager sa proširenim perzistencionim kontekstom održava stanje referenci na upravljane entitete i posle potvrde (commit) transakcije. Svi objekti iz prethodne transakcije (ili transakcija ako ih ima više) ostaju u upravljanom stanju. Operacije persist, remove, merge, i refresh mogu biti pozivane bez obzira da li je transakcija otvorena ili ne.

3.4 PersistenceUnit

Perzistentna jedinica (persistence unit) predstavlja logičku grupu koja obuhvata: EntityManagerFactory i njegove entitetske menadžere, zajedno sa njihovim

konfiguracionim informacijama. Skup upravljanih klasa uključenih u persistence unit i upravljanih od strane

Entity Manager-a. Metapodatke preslikavanja (u formi anotacije i/ili XML metapodataka) koji

specificiraju preslikavanje klasa u bazu podataka.

3.4.1 PersistenceUnit - pakovanje U Java EE okruženju, ejb-jar, war, ear, ili aplikacioni klijent jar može definisati persistence unit. U okviru ovih paketa može se definisati proizvoljan broj persistence unit-a. PersistenceUnit se može spakovati u jedan ili više jar datoteka koje se nalaze unutar war ili ear datoteke ili u okviru skupa klasa ejb-jar datoteke ili u war classes direktorijumu, ili kao kombinacija prethodnih pristupa.

Persistence unit se definiše u persistence.xml datoteci. Jar datoteka ili direktorijum čiji META-INF direktorijum sadrži persistence.xml fajl naziva se root perzistente jedinice (persistence unit).

U Java EE, root perzistentne jedinica se može naći na nekom od sledećih mesta: ejb-jar fajl WEB-INF/classes direktorijum war datoteke jar datoteka u the WEB-INF/lib direktorijumu war datoteke jar datoteka u root-u ear datoteke jar datoteka u ear direktorijumu biblioteke application client jar datoteka

3.4.2 Deskriptor fajl - persistence.xml

17

Page 18: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Fajl persistence.xml definiše persistence unit. Može se koristiti za specificiranje perzistentnih klasa uključenih u persistence unit, definisanje data source-a, SQL dialekta, URL-a i ostalih drugih konfiguracionih promenljivih vezanih za EntityManager i EntityManagerFactory. Datoteka persistence.xml se nalazi u META-INF direktorijumu root-a persistence unit-a. Datoteka se sastoji od jedne ili više persistence-unit elemenata. Persistence-unit element se sastoji od sledećih podelemenata i atributa: description, name, provider, transaction-type, jta-data-source, non-jta-data-source, mapping-file, jar-file, exclude-unlisted-classes, class i properties. Atribut name je obavezan, ostali atributi i elementi su opcioni.

3.5 EntityManagerFactory

EntityManagerFactory služi za dobijanje EntityManager-a. Kada koristimo container-managed EntityManager-e u Java EE okruženju, aplikacija najčešće nema direktnu interakciju sa EntityManagerFactory jer se EntityManager dobija kroz injection ili JNDI lookup mehanizam, tako da kontejner upravlja interakcijama transparentno ka aplikaciji. Kada se koristi application-managed EntityManager aplikacija mora koristiti EntityManagerFactory radi upravljanja EntityManager-om i životnim ciklusom persistence context-a. U oba navedena slučaja, kada koristimo više perzistentnih jedinica (persistence unit) aplikacija mora jasno specificirati sa kojom perzistentnom jedinicom se radi.[6]

3.5.1 Dobijanje EntityManagerFactory instance u SE okruženju Van aplikativnog Java EE kontejnera, javax.persistence.Persistence klasa se može koristiti za dobijanje EntityManagerFactory instance. Aplikacija kreira EntityManagerFactory pozivanjem createEntityManagerFactory metode klase javax.persistence.Persistence.

U slučaju application-managed EntityManager-a ( kao što je slučaj pri korišćenju JPA van aplikacionog server) EntityManager se dobija preko EntityManagerFactory.

EntityManagerFactory API koji se koristi za dobijanje application-managed EntityManager-a je isti bilo da se koristi u okviru Java EE ili Java SE okruženja.

3.6 Query API

3.6.1 Query interfejs

Query API se koristi za oba tipa upita i statičke i dinamičke upite. Query API takođe podržava povezivanje imenovanih parametara kao i kontrolu nad paginacijom. Zbog važnosti Query API-ja biće prikazan intefejs:

public interface Query {

18

Page 19: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

public List getResultList(); public Object getSingleResult();

public int executeUpdate(); public Query setMaxResults(int maxResult); public Query setFirstResult(int startPosition);

public Query setHint(String hintName, Object value);

public Query setParameter(String name, Object value);

public Query setParameter(String name, Date value, TemporalType temporalType); public Query setParameter(String name, Calendar value, Temporal- Type temporalType);

public Query setParameter(int position, Object value); public Query setParameter(int position, Date value, TemporalType temporalType); public Query setParameter(int position, Calendar value, Temporal- Type temporalType);

public Query setFlushMode(FlushModeType flushMode); }

Rezultat upita koji vraća više objekata je tipa Object[]. Ako se parametar po imenu ne slaže sa očekivanim imenom parametra u upitu ili ako se parametar po poziciji ne slaže sa očekivanim ili ako ne odgovaraju tipovi parametara biće bačen izuzetak IllegalArgumentException. Osim metode executeUpdate ostale metode ne zahtevaju transakcioni kontekst. Metode getResultList i getSingleResult ne zahtevaju transakcioni kontekst. Ako je EntityManager sa Transaction-scoped perzistencionim kontekstom, entiteti iz rezultata upita biće odvojeni od konteksta. Ako je u pitanju prošireni životni vek EntityManager ovi entiteti će biti upravljani. Runtime izuzeci drugačiji od NoResultException i NonUniqueResultException bačeni od metoda iz Query interface uzrokuju odustajanje (rollback) tekuće transakcije.

3.6.2 Imenovani parametri Imenovani parametar predstavlja promenljivu upita koja ima prefiks ":". Korišćenje imenovanih parametara je garantovano za EJB QL, ali se ne može primeniti na prirodne SQL upite. Prenosivost (portabilnost) SQL upita je garantovana samo za pozicine parametre.

19

Page 20: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

3.6.3 Imenovani upiti Imenovani upiti su statički upiti prikazani metapodacima. Imenovani upiti se mogu definisati EJB QL ili prirodnim SQL jezikom. Imenovani upiti imaju oblast važenja na nivou persistence unit-a.

3.6.4 Polimorfni upiti

Podrazumeva se da su svi upiti polimorfni. To znači da se u FROM uslovu upita mogu naći entiteti ne samo iste klase već i entiteti koji su podklase. Rezultat upita predstavljaju svi entiteti koji zadovolajvaju uslov.

3.6.5 SQL prirodni upiti Upiti se mogu postavljati i korišćenjem prirodnog SQL jezika. Rezultat prirodnog SQL upita se može sastojati od entiteta, skalarnih vrednosti, ili njhove kombinacije. Kada su u pitanju entiteti oni mogu biti i različitih tipova. SQL upiti su omogućeni da bi se koristili samo u slučajevima kada je to neophodno (ili gde se EJB QL ne mogu koristiti). Ovi upiti nisu prenosivi (portabilni) između različitih baza podataka. Kada SQL upit vraća više entiteta kao rezultat izvršenja, eniteti i preslikavanja kolona u polja odgovarajućih entiteta se prethodno moraju definisati korišćenjem SqlResultSetMapping anotacije. Ovaj rezultujući set metapodataka se može upotrebiti za mapiranje JDBC rezultata u očekivane objekte. Ako se u rezultatu pojavljuje samo jedan tip entiteta onda se takođe koristi SqlResultSetMapping samo u jednostavnijoj formi.

3.7 Transakcije

U zavisnosti od tipa transakcije EntityManager-a, transakcione operacije EntityManager-a se mogu obezbediti preko operacija JTA ili korišćenjem resource-local EntityTransaction API-ja, koji se preslikava. EntityManager čije se tranasakcije kontrolišu kroz JTA nazivaju se JTA EntityManager-i, a EntityManager čije se transakcije kontrolišu preko EntityTransaction API-ja nazivaju se resource-local EntityManager-i. EntityManager može da se definiše kog će transakcionog tipa biti u vreme kada se EntityManagerFactory konfiguriše i kreira. U slučaju container-managed EntityManager, EntityManager mora biti JTA tipa. JTA EntityManager-i su jedini koji su specificirani za korišćenje u Java EE kontejnerima. U slučaju application-managed EntityManager mogu se koristiti bilo JTA EntityManager ili resource-local EntityManager.

Oba tipa menadžera- i JTA EntityManager-i i resource-local EntityManager-i su po specifikaciji Java EE Web i EJB kontejnera neophodni za implementaciju. U okviru EJB okruženja, JTA EntityManager se najčešće koristi. Uopšteno gledano, u Java SE okruženju samo su resource-local EntityManager-i podržani.

20

Page 21: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

3.7.1 JTA EntityManager U slučaju kada su transakcije EntityManager-a kontrolisane kroz JTA, EntityManager se naziva JTA EntityManager. JTA EntityManager učestvuje u tekućoj JTA transakciji, koja je započeta i potvrđena (committed) eksterno i propagirana u naredni sloj resource manager-a.

3.7.2 Resource-local EntityManager EntityManager čije transakcije se kontrolišu kroz EntityTransaction API su resource-local EntityManager. Ovaj tip, resource-local EntityManager transakcija je preslikan u resource Transaction preko persistence provider-a. Resource-local EntityManagers mogu koristiti serverske ili lokalne resurse da bi se konektovali na bazu podataka i one ne znaju za prisustvo JTA transakcija koje mogu biti ili ne aktivne.

4. Hibernate

4.1. Istorija

Hibernate je jedno od najpopularnijih ORM rešenja današnjice, dizajniran specifično za Javu. Projekat je započeo inženjer Gavin King 2001., s namerom da nadomesti dotadašnje popularno rešenje za očuvanje objekata, CMP Entity Beans, koje je bilo dovoljno moćno i fleksibilno da zadovolji potrebe samo najjednostavnijih aplikacija. Projekat je započet kao neprofitni, open-source projekat, koji se pre svega razvijao s obzirom na zahteve korisnika i firmi koje su ga upotrebljavale. Hibernate se s vremenom razvio u praktično rešenje koje stavlja naglasak na produktivnost. Početkom 2003. godine jboss.org Inc je preuzeo projekat, omogućivši time još bolju finansijsku i tehničku podršku projektu.

4.2. Hibernate paketi

Uz osnovni proizvod, Hibernate Core, koji omogućava osnovnu funkcionalnost, razvija se i više dodatnih paketa koji omogućavaju kompatibilnost s ostalim tehnologijama ili drugačiji pristup preslikavanju.

4.2.1 Hibernate Core

Hibernate Core, ili jezgro, je osnovni ORM servis za trajnost podataka. Kao osnovu korisničkog interfejsa obuhvata vlastiti API, upitni jezik HQL (vrlo sličan SQL-u), te metapodatke za mapiranje koji se čuvaju u XML formatu. Hibernate Core je takođe nezavisan od izvršnog okruženja na kom se koristi.

4.2.2 Hibernate Annotations

Zajedno s JRE 5.0 uvedena je nova mogućnost Jave: anotacije koda. Hibernate Annotations je modul koji iskorištava to svojstvo: dozvoljava definisanje metapodataka preko anotacija koje su uklopljene u sam aplikacijski kod. Hibernate Annotations su vrlo korisne i intuitivne, te se mogu koristiti kao dopuna ili zamena standardnom čuvanju metapodataka za mapiranje u XML formatu. Korišćenjem anotacija umanjuje se broj

21

Page 22: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

linija koda potreban za preslikavanje meta podataka u poređenju sa korišćenjem XML datoteka, takođe se povećavaju mogućnosti refaktorisanja. [5]

4.2.3 Hibernate EntityManager

Modul koji implementira neke mogućnosti definisane JPA specifikacijom: interfejs, pravila trajanja perzistentnih objekata i neke dodatne mogućnosti upita. Hibernate EntityManager je u principu samo „omotač“ Hibernate Core-a koji omogućava JPA kompatibilnost, te se vrlo jednostavno može vratiti na standardni Hibernate interfejs.

4.2.4 Hibernate Shards

Često nismo u mogućnosti da sve svoje relacione podatke smestimo u jednu bazu podataka. Prosto ponekad postoji prevelika količina podataka, koja zahteva distribuiranu arhitekturu sa višestrukim relacionim bazama podataka. Hibernate ljuštura je projektovana tako da obuhvati i smanji ovu složenost.

4.2.5 Hibernate validator

Hibernate validator omogućava da uz pomoć anotacija izrazimo domenska ograničenja koja će se provlačiti kroz sve nivoe našeg sistema.

4.2.6 Hibernate Search

Hibernate pretraživač nam pruža moć pretraživača celog teksta u okviru perzistentnog domenskog modela pomoću anotacija i uobičajnog API-ja. Interno, Hibernet pretraživač koristi Apache Lucene ostavljajući mogućnost korišćenja originalnog Lucene API-ja. U zavisnosti od potreba aplikacije, Hibernate pretraživač radi dobro i u neklasterovanom i klasterovanom načinu rada, pružajući sinhrono i asinhrono ažuriranje indeksa, birajući između vremena odgovora, povezanosti i ažuriranja indeksa.

4.2.7 Hibernate Tools

Hibernate alati su potpuno nova grupa alata za Hibernate 3, implementirana kao integrisani komplet Eclipse6 dodataka (plugins) zajedno sa Ant zadatkom (Ant task) za integrisanje u ciklus izgradnje (build cycle).

6 http://www.ecl ipse.org/

22

Page 23: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Sastoji se od sledećih komponenti: Editor preslikavanja (Mapping Editor) – Editor Hibernate XML datoteke za

preslikavanje, podržava auto-kompletiranje (auto-completion) imena klasa, polja, tabela i kolona, i obeležavanje (highlighting) sintakse;

Konzola (Console) – Hibernate konzola omogućava da se konfigurišu konekcije baze podataka, prikaz klasa i njihovih međusobnih asocijacija i podržava interaktivno izvršenje HQL upita nad bazom kao i iščitavanja rezultata upita ;

Obrnute tehnike (Reverse Engineering) – Najmoćnija spsobnost Hibernate alata je obrnuta tehnika koja na osnovu baze podataka generiše domenske klase i Hibenate datoteke preslikavanja, anotirane entite, HTML dokumentaciju, i to sve za samo par sekundi;

Čarobnjaci (Wizards) – Obezbeđeno je nekoliko čarobnjaka, uključujući čarobnjaka za brzo generisanje Hibernate konfiguracione datoteke (cfg.xml) i Hibernate konfiguracije konzole ;

Ant zadatak (Ant task) – Ant zadaci omogućavaju da se izvrši generisanje šeme, generisanje preslikavanja, ili generisanje Java koda.

4.3. Arhitektura Hibernate okvira

Hibernate okvir omogućava nekoliko različitih pristupa prilikom odabira servisa koje okvir pruža, a koji će se koristiti u razvoju aplikacije. Tri ključna servisa, odnosno komponente Hibernate okvira su:

upravljanje konekcijama (Connection Management), upravljanje transakcijama (Transaction management) objektno-relaciono preslikavanje (Object-Relational mapping).

U zavisnosti od toga koje komponenete okvira se koriste u razvoju aplikacije, razlikuju se dve osnovne arhitekture, tzv. „Lite“ i „Full cream“ arhitektura.

Pod „Lite“ arhitekturom podrazumeva se korišćenje samo komponente za objektno-relaciono preslikavanje, a upravljanje transakcijama i obezbeđivanje JDBC konekcija je prepušteno aplikaciji.

„Full Cream“ arhitektura podrazumeva korišćenje sve tri komponente.

23

Page 24: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Slika 11: Arhitektura Hibernate okvira [7]

4.4. Metode razvoja uz pomoć Hibernate-a

S obzirom na ishodišnu tačku projekta koji zahteva perzistentnost objekata, odnosno projektnih zahteva, postoje različiti tipovi razvojnih puteva. Hibernate svojim pomoćnim alatima podržava sledeće načine razvoja:

top-down – počinje se od postojećeg domenskog modela koji je već implementiran u Javi, na osnovu kojeg se izrađuje šema baze podataka. Ovakvi se slučajevi javljaju kada su određeni samo prezentacioni ili poslovni sloj aplikacije. Kako u ovom slučaju objekti određuju oblik same šeme podataka u bazi, ovaj je način najpovoljniji većini Java programera koji tako dobijaju odrešene ruke prilikom kreiranja objekata unutar aplikacije jer ne podležu nikakvim ograničenjima koje bi eventualno nametala baza podataka.

bottom-up – obrnuto od gore spomenutog načina, u ovome se načinu kreće od već definisane relacione šeme baze podataka i modela. U ovakvom slučaju najpovoljnije je koristiti alate koji će izvući metapodatke iz baze podataka, koji se kasnije mogu upotrebiti kako bi se stvorile datoteke za mapiranje, objekti u Javi ili anotirani Java kod (EJB 3.0 entity classes). Ovaj postupak, međutim, ne može

24

Page 25: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

pretpostaviti sve asocijacije između ciljnih objekata, tako da je neke stvari potrebno podesiti ručno.

middle-out – neki programeri preferiraju početi od XML datoteke za mapiranje, pa pomoću alata stvoriti šemu i potrebne klase . Okosnica takvog razvoja su očito datoteke za mapiranje, te se glavne izmene vrše upravo na njima, prema čijem se predlošku pomoću spomenutih alata menja ostatak aplikacije. Ovo je poprilično složen postupak, te je namenjen samo iskusnijim Hibernate programerima.

meet-in-middle – najteži mogući slučaj se javlja kada je potrebno spojiti već postojeće Java klase s već postojećim šemama podataka. U ovakvom slučaju Hibernate ne pomaže mnogo, već je potrebno prilagođavati i klase i šemu ne bi li se mogla uspostaviti veza. Datoteke za mapiranje se u ovom slučaju gotovo uvek izrađuju ručno. Ovakvi slučajevi su, na sreću, vrlo retki i javljaju se obično kao posledica lošeg menadžmenta projekta.

4.5. Hibernate okruženje

Što se tiče performansi računara neophodnih za njegovo korišćenje Hibernate zahteva sledeće[5] :

• Hibernate 2 zahteva JDK(Java Development Kit) 1.2 ili višu(1.4.2 i 1.5.0 se preporučuju)

• Hibernate 3 zahteva JDK 1.3.1 ili višu(1.4.2 i 1.5.0 se preporučuju) • 128 MB RAM • 50 MB prostora na hard disku • 400 MHz brzina procesora • Hibernate okvir je napisan u Java programskom jeziku tako da se može

izvršavati na svim operativnim sistemima na kojima se može izvršavati i Java(Windows, Unix, Linux i dr.)

• Hibernate okvir podržava sledeće baze podataka i njihove SQL dijalekte: Oracle, DB2, Sybase, MS SQL Server, PostgreSQL, MySQL, FrontBase, Ingres, Mckoi SQL, HypersonicSQL, SAP DB, Interbase, Pointbase, Progress, Informix i Firebird.

Što se tiče biblioteka neophodnih za rad s Hibernate-om u projekat je potrebno uključiti sledeće osnovne biblioteke (oznaka verzija zamjenjuje brojeve koji predstavljaju verziju biblioteke):

• hibernate3.jar – osnovna biblioteka • log4j-verzija.jar – modul za beleženje akcija (eng. logger), vrlo korisno tokom

razvoja aplikacije (debugging) • cglib-verzija.jar – interfejs za stvaranje posrednika (eng. proxy) za perzistentne

klase• jta.jar – interfejs za komunikaciju rukovodilaca transkacija i ostalih procesa

uključenih u prenos podataka • antlr.jar – ANTLR jezički parser (LL(k)), služi za parsiranje SQL i HQL upita • dom4j.jar – DOM interfejs za Javu, koristi se za čitanje XML konfiguracionih

datoteka • ehcache.jar – služi za dinamičko čuvanje trajnih objekata (kako bi se komunikacija

s bazom svela na najmanju moguću) • mysql-connector-java-verzija-bin.jar – driver za vezu s MySQL DBMS-om

25

Page 26: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

• c3p0-verzija.jar – third-party menadžer vezama s bazom podataka (Connection pool)

• commons-collections-verzija.jar – sadrži Hibernate-ove posebne tipove kolekcija• commons-logging-verzija.jar – omogućava spajanje na modul za beleženje akcija

4.6. Konfigurisanje okvira

Kako Hibernate, kao perzistentni okvir, može da komunicira sa velikim brojem različitih sistema za upravljanje bazama podataka (SUBP), i, takođe, može da se izvršava u različitim okruženjima – u okviru samostalnih (standalone) aplikacija, u okviru Web aplikacija, ili J2EE aplikacija to zahteva različite načine konfigurisanja okvira. Bez obzira na okruženje i bazu podataka sa kojom komunicira aplikacija, konfigurisanje okvira može da se logički podeli u dve celine. U prvom delu obezbeđuju se konfiguracioni podaci koji su neophodni okviru da bi pristupio bazi podataka, a drugi deo čine konfiguracioni podaci kojima se obezbeđuje preslikavanje između perzistentnih klasa aplikacije i odgovarajućih tabela u relacionoj bazi podataka.

Centralna klasa pomoću koje se vrši konfigurisanje i pokretanje Hibernate okvira je klasa org.hibernate.cfg.Configuration. Kao što se može videti na sledećoj slici, prilikom kreiranja, ovoj klasi je potrebno obezbediti konfiguracione podatke, na osnovu kojih Configuration objekat kreira jedno pojavljivanje (singleton) klase SessionFactory. Jedno pojavljivanje SessionFactory klase, u suštini predstavlja potpuno konfigurisan Hibernate okvir koji omogućava komunikaciju sa jednom bazom podataka. Pored toga što Configuration objekat kreira jedinstveno (singleton) pojavljivanje SessionFactory klase, stanje ovog objekta nije moguće menjati nakon kreiranja. Naziv klase SessionFactory upućuje na njenu namenu – ona je zadužena za kreiranje objekata klase Session prilikom svake interakcije sa bazom podataka.

Slika 12: Konfigurisanje Hibernate okvira [7]

26

Page 27: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

4.6.1 Konfiguracioni podaci

Konfiguracioni podaci mogu da se podele u dve celine: podaci neophodni da bi se pristupilo bazi podataka, i podaci na osnovu kojih se vrši preslikavanje atributa perzistentnih klasa ka kolonama tabela u relacionoj bazi podataka.

Hibernate nudi dve opcije, odnosno dva formata u kojima se mogu obezbediti podaci: u okviru standardne datoteke za definisanje osobina (properties datoteke), pod nazivom hibernate.properties, ili u XML formatu, u datoteci pod nazivom hibernate.cfg.xml. Bez obzira na izabrani format, datoteke moraju da budu smeštene u classpath putanji aplikacije, a ukoliko se obe datoteke nađu u classpath putanji, podaci iz datoteke hibernate.cfg.xml prekriće podatke iz datoteke za definisanje osobina.

Konfiguraciona datoteka mora da sadrži definiciju sledećih pet osobina: connection.driver_class - upravljački program (driver) za izabrani

sistem za upravljanje bazom podataka (SUBP); connection.url - JDBC URL do baze podataka. JDBC URL sastoji se iz

simboličkog imena upravljačkog programa, IP adrese mašine na kojoj se nalazi SUBP, porta na kome je podignut SUBP i imena baze podataka sa kojom program treba da uspostavi konekciju;

connection.username - korisničko ime za pristup bazi podataka; connection.password - lozinku za pristup bazi podataka; dialect - naziv SQL dijalekta za specifičnu bazu podataka

Jedan od načina za definisanje drugog dela konfiguracionih podataka, koji se odnose na preslikavanja između perzistentnih klasa i tabela baze podataka jesu XML datoteke za preslikavanje.

Nakon kreiranja svih datoteka za preslikavanje, potrebno je za svaku datoteku dodati mapping element sa putanjom do kreirane datoteke u hibernate.cfg.xml datoteci. Zadate putanje su relativne u odnosu na classpath putanju aplikacije.

4.6.2 Pokretanje okvira

Pokretanje Hibernate okvira moguće je realizovati na više načina. Jedna od mogućih opcija je:

Configuration cfg = new Configuration(); SessionFactory factory = cfg.configure().buildSessionFactory();

Kada se pozove konstruktor new Configuration() Hibernate traži fajl hibernate.properties u glavnom folderu projekta. Ukoliko ih pronađe svi hibernate.properties fajlovi su učitani i dodati u Configuration objekat. Kada se pozove metoda configure() Hibernate traži fajl hibernate.cfg.xml

27

Page 28: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

u glavnom folderu projekta i baca izuzetak ukoliko ga ne nađe. Fajl hibernate.cfg.xml može se postaviti i u neki drugi folder, ali je onda obavezno u metodi configure navesti putanju do njegovog fajla.

Sledi kreiranje konfiguracionog fajla za Hibernate aplikaciju. Preporučuje se da konfiguracioni fajl zove hibernate.cfg.xml i da se postavi u source direktorijum. Tako će ovaj fajl ostati u glavnom folderu projekta nakon kompajliranja i Hibernate okvir će ga automatski naći.

4.7. Hibernate interfejs

Hibernate API sadrži mnoštvo objekata različite namene. Nekoliko tih objekata čini osnovu interfejsa te se koriste prilikom pristupa bilo kojoj bazi.

4.7.1. Configuration objekat

Objekat koji čuva podatke potrebne za uspostavljanje veze s bazom podataka, kao što su : • tip DBC-a (npr. JDBC) • adresa servera na mreži • tip DBMS-a (MS SQL, Informix, ORACLE, MySQL, ...) • SQL dijalekt

Ovi podaci se čuvaju u objektu: • prilikom inicijalizacije objekta, pomoću objekta SettingFactory • u kodu preko metode configure([String filename]), gde je filename

putanja configuracijske datoteke. Ukoliko se argument izostavi, pretpostavlja se putanja „\hibernate.cfg.xml“

Configuration objekat služi prvenstveno za stvaranje objekta SessionFactory, koji je osnova komunikacije s bazama podataka. SessionFactory se stvara metodom buildSessionFactory(). [2]

4.7.2. SessionFactory objekat

Objekat koji služi za uspostavu komunikacije s bazom podataka, njegova inicijalizacija predstavlja normalan način pokretanja Hibernate-a.

SessionFactory prima podatke na dva načina: • od objekta Configuration koji ga je instancirao • iz konfiguracijske datoteke (čiju putanju treba navesti ako se ne nalazi na

predviđenom mestu)

SessionFactory pozivom metode openSession() uspostavlja komunikaciju s DBMS-om te kontrolu nad vezom predaje instance objekta Session kojeg instancira. SessionFactory je thread-safe objekat i u praksi je dovoljna samo jedna njegova instanca po bazi podataka za sve aplikacije. Inicijalizacija više instanci SessionFactory-a se stoga ne preporučuje.[2]

28

Page 29: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

4.7.3. Session objekat

Session objekat kreiramo uvek iz SessionFactory-ja. SessionFactory se u ovom slučaju ponaša kao ConnectionPool objekat, dok Session objekat više liči na Connection objekat u DBC-u (Slika 13).

Pri isčitavanju nekog objekta iz baze koristimo Session objekat direktno ili indirektno. Primer direktnog korišćenja Session objekta je pozivanjem metode get() nad samim Session objektom, ili kreranjem Query objekta takođe iz Session objekta (Query je u toj analogiji sličan PreparedStatement u JDBC-u). Indirektno korišćenje Session objekta bi bio korišćenjem objekta koji je u vezi sa Session objektom. Objekat koji nije bio učitan Session objektom može se eksplicitno koristiti zajedno sa Session objektom na nekoliko načina, najjednostavniji je pozivom metode update() Session objekta sa argumentom odgovarajućeg objekta.

Slika 13: Sličnosti između Hibernate i JDBC objekata [5]

Pored ovoga Session objekat obezbeđuje i funkcionalnost keširanja, upravlja lenjim učitavanjem objekata i nadgleda promene nad povezanim objektima (kako bi se te promene na pravi način odrazile i na samu bazu). Hibernate transakcija je obično korišćena na sličan način kao i JDBC transakcija. Ona grupiše međusobno zavisne Hibernate operacije, dozvoljavajući im da se kompletiraju ili ponište (roll back) automatski, takođe i izoluje operacije od spoljašnjih promena baze.

4.7.3.1 Operacija čuvanja objekta

Kreiranje objakta preslikane klase ne znači i njegovo automatsko čuvanje u bazi podataka. Dokle god ekplicitno ne sačuvate objekat Hibernate Session-om, objekat je transijentan kao i ostali Java objekti. U Hibernate koristimo metodu save() Session objekta kako bi sačuvali željeni zapis u bazi, i to na sledeći način:

public Serializable save(Object object) throws HibernateException

29

Page 30: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

public void save(Object object, Serializable id) throws HibernateException

public Serializable save(String entityName,Object object) throws HibernateException

Sve save() metode uzimaju reference transijentnih objekata (različitih od null) kao argument. Hibernate očekuje da pronađe preslikavanje za klasu transijentnog objekta, pošto ne može da sačuva nepreslikane objekte. Kada čuva objekat, moguće je da korisnik potisne vrednost identifikatora generisanog od strane Hibernate-a zadavanjem id polja, ili pozivanjem alternativne save() metode koja uzima id objekat kao argument. Ovo je veoma korisno kada entitet nema sopstveno id polje, međutim ova metoda se može koristiti i u tom slučaju. Id ne sme biti null i mora biti serijabilan. Ako je id polje primitivnog tipa može se koristiti odgovarajući objekat omotač (wrapper). Na primer, za tip int će se koristiti java.lang.Integer. Sve save() metode generišu događaj org.hibernate.event.SaveOrUpdateEvent.Nije svrsishodno čuvati već sačuvani objekat, kao ni ažurirati (update) transijentni objekat te stoga koristimo metodu saveOrUpdate(). Hibernate koristi identifikator objekta kako bi odredio da li je potrebno ubaciti novi red u bazi ili ažurirati već postojeći. Potpis te metode izgleda ovako:

public void saveOrUpdate(Object object) throws HibernateException

Jednom kada je objekat sačuvan, Hibernate upravlja ažuriranjem baze tokom menjanja polja objekta. Kako bi podržali zahtevano ponašanje novog EJB 3.0 EntityManager-a, dodata je u API i metoda persist(). Ona se ponaša isto kao i save(), osim što ne garantuje da će entitetima biti odmah dodeljene vrednosti primarnog ključa.

4.7.3.2 Učitavanje entiteta

Hibernate Session objekat pruža nekoliko load() metoda za učitavanje entiteta iz baze. Svaka load() metoda zahteva primarni ključ objekta kao identifikator. Dodatno, Hibernate mora znati koje ime klase ili entiteta da koristi kako bi našao objekat sa tim id-jem. Poslednje, objekat vraćen load() metodom mora se prebaciti (cast) u željenu klasu.

Osnovne load() metode su:

public Object load(Class theClass, Serializable id) throws HibernateException

30

Page 31: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

public Object load(String entityName, Serializable id) throws HibernateException

public void load(Object object, Serializable id) throws HibernateException

Poslednja load() metoda uzima objekat kao argument. Objekat bi trebao da bude istog tipa (klase) kao i onaj koji želimo da učitamo, i trebao bi da bude prazan. Hibernate će popuniti taj objekat sa traženim objektom.

Druge load() metode kao argument koriste zaključavanja (lock mode). Zaključavanja određuju da li bi Hibernate trebao da traži objekat u kešu, i koji nivo zaključavanja baze podataka bi Hibernate trebao da koristi za red (ili redove) podataka koje predstavljaju objekat. Hibernate autori tvrde da će obično sam Hibernate odabrati pravi (odgovarajući) nivo zaključavanja, međutim postoje situacije kada je ručno zaključavanje od značaja. Takođe, baza podataka može odabrati sopstvenu strategiju zaključavanja – na primer, blokiranje cele tabele pre nego nekoliko redova u okviru tabele. Počinjući od najmanje restriktivnog pa do najrestriktivnijeg, postoje sledeći nivoi zaključavanja:

NONE - Ne koristi zaključavanje na nivou reda (row-level locking), i koriste se keširani objekti ako su dostupni; ovo je podrazumevana vrednost Hibernate-a.

READ - Ne dozvoljava SELECT upite nad podacima koji su u toku transakcije, sve dok se ne potvrde (commit) promene.

UPGRADE - Koristi SELECT FOR UPDATE SQL sintaksu kako bi zaključali podatke dok se transkacija ne završi.

UPGRADE_NOWWAIT: Koristi NOWWAIT ključnu reč (za Oracle), koja odmah vraća grešku ako druga nit koristi taj red. U ostalim slučajevima se ponaša kao i UPGRADE nivo.

Svi ovi nivoi zaključavanja su statična polja klase org.hibernate.LockMode. Metoda load() koja koristi zaključavanje ima sledeće potpise:

public Object load(Class theClass, Serializable id, LockMode lockMode) throws HibernateException

public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException

U slučaju da nije sigurno da traženi objekat postoji u bazi ne bi trebalo koristiti metodu load(). U tom slučaju treba da se koristi get() metoda. Metoda load() će

31

Page 32: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

baciti izuzetak ako jedinstveni id nije pronađen u bazi, dok će get() metoda vratiti null referencu. Kao i load() metoda i get() metoda uzima identifikator i ime entiteta ili klase za argumente.

Takođe postoje i dve metode koje koriste zaključavanja. Potpis get() metoda je:

public Object get(Class clazz, Serializable id) throws HibernateException

public Object get(String entityName, Serializable id) throws HibernateException

public Object get(Class clazz, Serializable id, LockMode lockMode) throws HibernateException

public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException

Za ime entiteta datog objekta (slično kao ime klase) može se koristiti metoda Session objekta:

public String getEntityName(Object object) throws HibernateException

4.7.3.3 Osvežavanje entiteta

Hibernate pruža mehanizam za osvežavanje perzistentnih objekata iz baze korišćenjem jedne od metoda refresh() Session objekta:

public void refresh(Object object) throws HibernateException

public void refresh(Object object, LockMode lockMode) throws HibernateException

32

Page 33: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

4.7.3.4 Ažuriranje entiteta

Sve promene napravljene nad perzistentnim objektima Hibernate automatski pamti u bazi. Hibernate sesija će korišćenjem SQL-a upita napraviti potrebne promene u bazi. Iz perspektive programera nije potreban nikakav posao kako bi se to obezbedilo, osim ako se ne želi da natera Hibernate da potvrdi (commit) sve te promene. Takođe može se ispitati da li je sesija „prljava“ te je potrebno potvrditi preostale promene. Kada se potvrdi Hibernate transakcija, on će sve to odraditi automatski . Metoda flush() primorava Hibernate da „očisti“ sesiju na sledeći način:

public void flush() throws HibernateException

Metodom isDirty() ispitujemo da li je sesija „prljava“:

public boolean isDirty() throws HibernateException

Takođe, Hibernate se može podesiti da koristi „čišćenje“ za sesiju metodom setFlushMode().

Metoda getFlushMode() nam vraća način čišćenja (flush mode) za trenutnu sesiju:

public void setFlushMode(FlushMode flushMode)

public FlushMode getFlushMode()

Postoje sledeći načini čišćenja: ALWAYS - Svaki upit očisti sesiju pre svog izvršenja AUTO - Hibernate upravlja čišćenjem kako bi garantovao da podaci dobijeni

upitom budu tačni COMMMIT - Hibernate čisti sesiju nakon potvrđivanja (commit) transakcije NEVER - Hibernate nikad neće sam očistiti sesiju, dok se eksplicitno u

aplikaciji ne pozove flush() metoda

Podrazumevano Hibernate koristi AUTO kao način čišćenja.[3]

4.7.3.5 Brisanje entiteta

Za brisanje entiteta iz baze podataka, Session objekat poseduje metodu delete() sa sledećim potpisom:

33

Page 34: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

public void delete(Object object) throws HibernateException

Ova metoda za argument uzima perzistentni objekat. Međutim, za argument se može uzeti i transijentni objekat sa identifikatorom jednakim id-u objekta koji se treba obrisati. U najjednostavnijem slučaju, u kojem prosto brišete objekat koji nije povezan sa ostalim objektima u bazi, ovo može biti korisno, ali mnogi objekti u bazi su međusobno povezani. Kako bi izbegli ovu vrstu problema, Hibernate može biti konfigurisan da pri brisanju objekta iz baze dozvoli da se obrišu i oni objekti sa kojima je ovaj u vezi.

Uzmimo za primer slučaj jakog objekta i kolekciju njegovih slabih objekata koje treba obrisati . Najlakši način da se obavi ovo jeste korišćenjem cascade atributa nad elementima kolekcije u okviru Hibernate preslikavanja. Podešavanjem ovog atributa na „obriši sve“ (delete), Hibernate će osigurati da brisanjem jakog objekta se obrišu i svi njegovi slabi objekti.

4.7.4 Transaction objekat

Hibernate API može postaviti ograničenja prenosa podataka, tako da se razmena podataka s bazom može dogoditi jedino unutar trajanja transakcije (koja započinje pozivom metode transactionBegin(), a završava pozivom metode commit()). Sva komunikacija s bazom podataka je virtualna i ostaje takva sve do poziva metode commit(), koja prisiljava izvršavanje naredbi koje su sačuvane unutar objekta Session. Postoji više načina ostvarivanja komunikacije u aplikacijama, a njihova primena zavisi od : • session-per-request – započinje sesiju kada god se ukaže potreba za komunikacijom s bazom podataka. Pri tome se obično započinje i samo jedna transakcija, unutar koje se izvrše svi potrebni prenosi • session-per-conversation – započinje jednu sesiju za niz komunikacija koje označavaju jednu operaciju (obrada podataka iz baze, recimo), koje se odvijaju kroz više transakcija unutar iste sesije. Na primer, jednom transakcijom se pristupa trajnim objektima, koji se potom odvoje od baze (eng. detach), zatim obrade, te idućom transakcijom ponovo vrate u bazu. Tek po završetku sesije promene će se zaista i dogoditi.

4.7.5 Query objekat

Ovaj objekat služi za direktno postavljanje upita bazi podataka. Upiti se mogu pisati u objektno-orjentisanom HQL-u (Hibernate Query Language) ili u običnom SQL-u. Rezultati izvršavanja upita su objekti klasa, kojima se može potom pristupiti iz objekta Query pojedinačno ili u obliku kolekcije (List). HQL omogućuje pritome pristup koji je prilagođen OOP-u jer dozvoljava korišćenje klasa kao odredišnih tipova unutar samih upita.

4.7.5.1 Prirodni SQL

Iako Hibernate preporučuje korišćenje HQL-a, kad god je to moguće, postoji mogućnost korišćenja i „čistog“ SQL-a. Jedan od razloga koričćenja SQL-a jeste taj što pojedine baze podataka poseduju određene mogućnosti kroz svoj SQL dijalekt koji nisu podržani u HQL-u.

34

Page 35: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Drugi razlog, je taj što ćete možda želeti da iz Hibernate aplikacije pozovete uskladištene procedure.

SQL izrazi se mogu modifikovati kako bi se usaglasili sa Hibernate ORM slojem. Potrebno je promeniti SQL za uključivanje Hibernate promenljivih, koje upućuju na objekte ili njihova polja. Da bi selektovali sva polja nad objektom koristi se {objjectname.*} ili selektovali pojedinačno {objectname.property}. Hibernate koristi preslikavanje kako bi preveo ime polja objekta u njegovu odgovarajuću SQL kolonu. Možda ovo nije očekivan način funkcionisanja, zato treba biti siguran da je SQL promenjen na pravi način kako bi osigurao potpunu podršku ORM-a. Hibernate podrška za čist SQL leži u org.hibernate.SQLInterface, koji proširuje org.hibernate.Query interfejs. Kroz aplikaciju SQL upit se kreira metodom createSQLQuery() Session objekta:

public SQLQuery createSQLQuery(String queryString) throws HibernateException

Pošto se prosledi tekst koji sadrži SQL upit, createSQLQuery() metodi, trebalo bi povezati SQL rezultat sa nekim entitetom, spajanjem ili skalarnim rezultatom. SQLQuery interfejs poseduje addEntity(), addJoin() i addScalar() metode za to. Metoda addEntity() za argument uzima promenljivu i ime klase ili entiteta, a addJoin() kao argument uzima promenljivu i putanju do spajanja.

4.7.5.1 Objektni HQL

HQL se koristi kako za isčitavanje podataka iz baze (SELECT), tako i za njihovo menjanje (INSERT, UPDATE, DELETE). HQL je jezik sa svojom sopstvenom sintaksom i gramatikom. To je objektno orjentisani jezik koji je sličan SQL-u, samo umesto da operiše nad tabelama i kolonama, HQL radi sa perzistentnim objektima i njihovim poljima. HQL je inspirsan SQL-om, a predstvalja inspiraciju za novi EJB upitni jezik (EJB QL). HQL upiti se prevode u konvncionalni SQL upit od strane Hibernate-a. Programeri obično nisu sigurni u optimizovanost Hibernate-ovog generisanog SQL-a. U slučaju da upiti postanu usko grlo performansi aplikacije, preporučuje se da se koriste SQL zapisi (opisani u nastavku teksta) tokom testiranja kritičnih komponenti. Ako se primeti bilo kakav prostor za optimizaciju, preporučuje se pre svega optimizacija HQL-a (ako je moguća), i tek nakon toga prelazak na čist SQL. Takođe, Hibernate 3 pruža statističke podatke kao JMX Mbean, koji se mogu koristiti za analiziranje Hibernate karakteristika. HQL se koristi ugnježdavanjem upita u createQuery() metodu Session objekta:

public Query createQuery(String queryString) throws HibernateException

35

Page 36: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Ova metoda za argument uzima validan HQL izraz, i kao rezultat vraća Query objekat. Query klasa nam pruža metode za vraćanje rezultata upita u vidu Java List-e, Iterator-a, ili kao jedinstveni rezultat. Druge funkcionalnosti podrazumevaju imenovane parametre, prelistavanje rezultata, kapacitet JDBC učitavanja i JDBC pauze (timeouts).

4.7.5.1.1 UPDATE

UPDATE menja pojedinosti postojećeg objekta u bazi. Entiteti u memoriji se neće ažurirati kako bi odrazile promene kao rezultat UPDATE izraza. Sintaksa ovog izraza se može prikazati na sledeći način:

UPDATE [VERSIONED] [FROM] path [[AS] alias] [, ...] SET property = value [, ...] [WHERE logicalExpression]

gde path predstavlja potpuno kvalifikovano ime entiteta, alias se mogu koristiti za skraćivanje referenci do određenih entiteta ili njihovih polja, i u upitima se moraju koristiti nedvosmisleno, a property predstavljaju imena polja entiteta u FROM putanji.

Za izvršavanje ovog upita se koristi metoda executeQuery(), Query objekta, koja kao rezultat vraća broj redova nad kojima je izvršena promena.

4.7.5.1.2 INSERT

HQL INSERT se ne može koristiti za direktno ubacivanje proizvoljnih entiteta. Za razliku od običnog SQL-a, u kojem se INSERT komanda može korisititi za ubacivanje bilo kojih podataka u tabeli on se može samo koristiti za ubacivanje entiteta kreiranih iz informacija koje su rezultat SELECT upita.

Sintaksa INSERT izraza izgleda ovako:

INSERT INTO path ( property [, ...])

gde path predstavlja potpuno kvalifikovano ime entiteta, a property imena polja entiteta izlistanih u FROM putanji ugnježdenog select upita.

4.7.5.1.3 SELECT

HQL SELECT se koristi za pretragu baze za klasama i njihovim poljima. Ovaj tip pretrage se uglavnom koristi za manje složene upite, međutim za složenije upite preporučuje se korišćenje Creteria API-ja.

Sintaksa SELECT izraza izgleda ovako:

36

Page 37: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

[SELECT [DISTINCT] property [, ...]] FROM path [[AS] alias] [, ...] [FETCH ALL PROPERTIES] WHERE logicalExpression GROUP BY property [, ...] HAVING logicalExpression ORDER BY property [ASC | DESC] [, ...]

gde path predstavlja potpuno kvalifikovano ime entiteta, alias se mogu koristiti za skraćivanje referenci do određenih entiteta ili njihovih polja, i u upitima se moraju koristiti nedvosmisleno, a property predstavljaju imena polja entiteta u FROM putanji.

U slučaju korišćenja FETCH ALL PROPERTIES, značenje lenjog učitavanja (lazy loading) će se poništiti, i sva polja traženog objekta će se učitati (ali ovo se neće nastaviti rekurzivno).

ORDER BY klauzula služi za sortiranje rezultata upita. Rezultat možete sortirati ili u rastućem (asc) ili u opdajućem (desc) redosledu, jednog ili više polja odvojenih zarezom.

4.8 Mehanizmi za poboljšanje performansi

Zbog problema s performansama koje uzrokuje upotreba posrednika za povezivanje s bazom podataka, Hibernate upotrebljava mnoge algoritme i metode za poboljšanje prenosa podataka. Među njima posebnu ulogu imaju metode pristupa podacima, koje mogu značiti veliku razliku po pitanju brzine rada aplikacije. Neke od najvažnijih i najčešće korišćenih metoda su:

lenjo preuzimanje (eng. lazy fetching) nestrpljivo preuzimanje (eng. eager fetching) nestrpljivo preuzimanje sa spajanjem (eng. eager fetching with join) grupno preuzimanje (eng. batch fetching) keširanje

4.8.1 Lenjo preuzimanje

Lenjo preuzimanje je metoda koja je pretpostavljena u slučaju da se nije ništa specificiralo. Prilikom peuzimanja podataka kojima se direktno ne pristupa, Hibernate umesto stvarnog objekta u memoriji stvori „držač mesta“ (engl. placeholder), koji služi umesto pravog objekta za sve operacije osim pristupanja njegovim poljima (jedino polje koje je dostupno u samom držaču je identifikator (eng. identifier), dakle metoda za preuzimanje istog). Prilikom prve operacije preuzimanja Hibernate će popuniti mesto u memoriji pravim objektom, oslobađajući držač prostora.

Ova metoda vrlo povećava performanse preuzimajući samo potrebne podatke i to prilikom prvog pristupa (dakle objekti kojima se uopše nije pristupilo nikada nisu zapravo preuzeti), čime se smanjuje promet podataka iz tabele.

37

Page 38: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Osim normalne metode postoji i vrlo lenjo preuzimanje (eng. extra lazy fetching) za kolekcije (eng. collections), koje neće zathevati preuzimanje kolekcije čak ni na pozive metoda kao što su size(), contains() ili isEmpty(), već će te podatke preuzimati direktno iz baze podataka.

4.8.2 Nestrpljivo preuzimanje

Iako je lenjo preuzimanje vrlo praktična metoda, ponekad je potrebno podatke odmah vratiti u memoriju; lenjo preuzimanje ne funkcioniše van trajnog konteksta, što znači da ne funkcioniše ako je veza s bazom zatvorena (što je, uostalom, i logično).

Pokušaj pristupa držaču prostora u ovom će slučaju izazvati izuzetak. Stoga je ponekad potrebno prisiliti Hibernate da pojedine objekte preuzme iz baze prilikom samog preuzimanja podataka. To se čini unutar datoteke za preslikavanje, označavanjem opcije lazy=“false“. Ovo je ponekad neophodan, ali i prihvatljiv kompromis na račun performansi aplikacije.

4.8.3 Nestrpljivo preuzimanje sa spajanjem

Ova metoda je prilagođena slučajevima kada objekat koji je preuzet i spremljen u memoriju logički i funkcionalno povezan s drugim objektom, a drugom je objektu moguće pristupiti spajanjem tabela u koje se ti objekti preslikavaju.

Ukoliko se podesi lazy=“false“ i fetch=“join“ , hibernate će prilikom preuzimanja prvog podatka odmah učiniti isto i za drugi.

4.8.4 Grupno preuzimanje

Grupno preuzimanje služi za smanjivanje broja pristupa bazi podataka (n+1 problem), tako što unapred preuzima veći broj objekata nego što je zatraženo; ovo se još naziva i optimizacija pogađanjem (blind-guess optimization), a služi u slučajevima kada aplikacija zahteva više objekata istog tipa, a koje bi morala preuzimati jedan po jedan (ili u nekoj drugoj, relativno maloj količini). U ovom se slučaju za tu klasu mora prilikom definicije preslikavanja navesti opcija batch-size=“n“ , gde je n broj istovremeno preuzetih objekata u jednom preuzimanju (SELECT). Ukoliko je broj zatraženih podataka veći od n, preuzimanje se vrši u više navrata. Ovo značajno smanjuje broj pristupa bazi pa je ovu metodu preporučljivo koristiti kada predstoji velik broj zahteva za instancama određenog objekta (preslikavanje kolekcija, na primer).

4.8.5 Keširanje

Keširanje predstavlja proces privremenog skladištenja kopija podataka na mestu gde im se može brže pristupiti. U Hibernate kontekstu, poboljšanje performansi se postiže privremenim čuvanjem – keširanjem materijaliziovanih perzistentnih objekata, kako bi se pri sledećem zahtevu za istim objektima, umesto operacija čitanja podataka iz baze, ovi objekti materijalizovali iz keš memorije.

Hibernate okvir podržava dva nivoa keširanja.

Prvi nivo keširanja je u opsegu izvršenja jedne sesije, odnosno u opsegu izvršenja jedne transakcije. Prvi nivo keširanja se u Hibernate-u podrazumevano koristi. Prvim

38

Page 39: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

nivoom keširanja se na nivou transakcije smanjuje broj generisanih SQL upita, odnosno, smanjuje se broj pristupa bazi podataka. Ilustracije radi, ukoliko se u toku transakcije materijalizuje jedan objekat, sve izmene koje se u toku transakcije izvrše na tom objektu čuvaju se u keširanoj kopiji objekta, da bi se umesto pojedinačnog ažuriranja stanja u bazi podataka nakon svake promene stanja objekta, ažuriranje izvršilo jednom, na kraju izvršenja transakcije.

Drugi nivo keširanja u Hibernate okviru je opcioni, odnosno, podrazumevano nije uključen. Keširanje drugog nivoa je šireg opsega od keširanja na prvom nivou. Objekte keširani na ovom nivou dostupni su svim sesijama kreiranim od strane SessionFactory objekta.

Hibernate u keš memoriju ne smešta same perzistentne objekte, već koristi određenu formu deserijalizacije objekata. Deserijalizacija se vrši tako što se atributi objekata smeštaju u odgovarajući niz vrednosti, dok se identifikator objekta koristi kao referenca na niz. Ovakvo stanje objekata se u Hibernate terminologiji naziva dehidrirano (dehydrated). Slično tome, process smeštanja objekata u keš memoriju, i proces kreiranja objekata domenskog modela iz keš memorije nazivaju se „dehidratacija“ i „hidratacija“ respektivno. Konceptualno gledano, keš memorija može da se posmatra kao mapa koja sadrži identifikatore objekata kao ključeve, a nizove kao vrednosti.

Ukoliko se želi koristiti keširanje drugog nivoa , neophodno je u konfiguracionim metapodacima navesti implementaciju koja će se koristiti. Hibernate podržava sledeće četiri open-source implementacije:

EHCache OSCache SwarmCache JBoss TreeCache

Nakon izbora implementacije, neophodno je definisati strategiju keširanja. Na raspolaganju su četiri strategije:

Read-only - Koristi se u situacijama kada se podaci često čitaju, ali nikad ne ažuriraju.

Read –Write - Koristi se u situacijama kad je podatke neophodno i ažurirati. Nonstrict Read-Write - Ova strategija ne garantuje da dve transakcije neće

simultano izvršiti izmenu istih podataka. Zbog toga je prikladna samo u situacijama kad se podaci često čitaju, a vrlo retko ažuriraju.

Transactional - Može da se koristi samo u JTA okruženjima. Različite implementacije podržavaju različit skup navedenih strategija.

Na drugom nivou keširanja, Hibernate podržava i mehanizam keširanja rezultata upita koje se razlikuje od keširanja objekata jer se tom prilikom ne keširaju objekti koji se iz upita dobijaju, već samo identifikatori objekata.

39

Page 40: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

5. Studijski primerNa osnovu analize informacionog sistema jednog trgovinskog preduzeća, a u svrhu prikazivanja funkcionalnosti objektno-relacionog preslikavanja, obradjen je modul koji demonstrira osnovne operacije manipulacije podacima o dobavljačima.

5.1 Podmodel

5.2 Konceptuelni model

5.3 Slučajevi korišćenja

5.3.1 Slučaj korišćenja: Unos novog dobavljača

Akteri SK: Korisnik Učesnici SK: Korisnik i sistemPreduslov: Sistem je uključen i radnik je ulogovan. Prikazana je forma za unos novog dobavljača.

Osnovni scenario:

Korisnik Sistem

1. Unosi potrebne podatke

2. Poziva sistem da snimi novog dobavljača

3. Snima podatke o novom dobavljaču

4. Prikazuje poruku o uspešnosti operacije

40

Page 41: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Alternativni scenario:4.1 Ukoliko sistem nije uspeo da snimi podatke o novom dobavljaču prikazuje poruku o tome.

5.3.2 Slučaj korišćenja: Izmena dobavljača

Akteri SK: Korisnik Učesnici SK: Korisnik i sistemPreduslov: Sistem je uključen i radnik je ulogovan. Prikazana je forma za izmenu dobavljača.

Osnovni scenario:

Korisnik Sistem

1. Unosi potrebne podatke

2. Poziva sistem da pronađe dobavljača

3. Pronalazi traženog dobavljača

4. Prikazuje podatke traženog dobavljača

5. Menja potrebne podatke

6. Poziva sistem da snimi izmenjene podatke

7. Snima izmenjene podatke

8. Prikazuje poruku o uspešnosti operacije

Alternativni scenario:4.1 Ukoliko sistem nije uspeo da pronađe traženog dobavljača prikazuje poruku o tome.8.1 Ukoliko sistem nije uspeo da snimi izmenjene podatke prikazuje poruku o tome.

5.3.3 Slučaj korišćenja: Brisanje dobavljača

Akteri SK: Korisnik Učesnici SK: Korisnik i sistemPreduslov: Sistem je uključen i radnik je ulogovan. Prikazana je forma za brisanje dobavljača.

Osnovni scenario:

Korisnik Sistem

1. Unosi potrebne podatke

2. Poziva sistem da izbriše dobavljača

3. Briše podatke o dobavljaču

4. Prikazuje poruku o uspešnosti operacije

41

Page 42: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Alternativni scenario:4.1 Ukoliko sistem nije uspeo da obriše podatke o dobavljaču prikazuje poruku o tome.

5.4 Dijagrami sekvenci

5.4.1 Dijagram sekvenci: Unos novog dobavljača

42

Page 43: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

5.4.2 Dijagram sekvenci: Izmena dobavljača

43

Page 44: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

5.4.3 Dijagram sekvenci: Brisanje dobavljača

5.5 Implementacija Hibernate-a

5.5.1 Preslikavanje podataka

Osnova preslikavanja u ovom primeru je preslikavanje klase u tabelu što je realizovano uz pomoć XML-a. Mapiranje klase Dobavljac je sačuvano u fajlu Dobavljac.hbm.xml.

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping> <class name="Dobavljac" table="Dobavljac"> <id name="DobavljacID" type="int"> <generator class="increment"/> </id>

<property name="Naziv" column="Naziv" type="string"/>

44

Page 45: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

<property name="Adresa" column="Adresa" type="string"/> <property name="Telefon" column="Telefon" type="string"/> <property name="Ziroracun" column="Ziroracun" type="string"/> </class> </hibernate-mapping>

5.5.2 Konfiguraciona datoteka

Konfiguracioni podaci koji su neophodni da bi se pristupilo bazi podataka nalaze se u konfiguracionoj datoteci hibernate.cfg.xml.

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property> <property name="connection.url">jdbc:derby://localhost:1527/diplomski</property> <property name="connection.username">vale</property> <property name="connection.password">vale</property>

<!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">1</property>

<!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.DerbyDialect</property>

<!-- Echo all executed SQL to stdout --> <property name="show_sql">false</property>

<!-- Mapping files --> <mapping resource="Dobavljac.hbm.xml"/>

</session-factory>

45

Page 46: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

</hibernate-configuration>

5.5.3 Manipulacija perzistentnim objektima

Tokom celog života aplikacije otvorena je jedna sesija što je omogućeno kroz klasu HibernateUtil.

public class HibernateUtil { private static final SessionFactory sessionFactory; static { try{ // Kreira SessionFactory na osnovu hibernate.cfg.xml sessionFactory=new Configuration().configure().buildSessionFactory(); }catch(Throwable ex){ System.err.println("Inicijalno kreiranje SessionFactory nije uspjelo! " + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory(){ return sessionFactory; }

}

Metode koje služe za manipulaciju podacima, kao i upravljanje transakcijama nalaze se u klasi DobavljacServis gde se uz pomoć objekta Session i njegovih metoda vrše osnovne operacije preuzimanja podataka iz baze i čuvanja u istoj.

public class DobavljacServis { Session session; Dobavljac dobavljac=new Dobavljac(); public DobavljacServis() { session=HibernateUtil.getSessionFactory().openSession();

}

void pokreniDBTransakciju() { session.beginTransaction();

46

Page 47: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

}

boolean snimiDobavljaca(Dobavljac dobavljac) { if (dobavljac.getStatus().equals("insert")) { session.save(dobavljac);return true; } else if (dobavljac.getStatus().equals("update")) { session.clear(); session.update(dobavljac); return true; } else if (dobavljac.getStatus().equals("delete")) { session.delete(dobavljac);return true; }else return false; }

void potvrdiDBTransakciju() { session.getTransaction().commit(); HibernateUtil.getSessionFactory().close(); }

void ponistiDBTransakciju() { session.getTransaction().rollback(); }

Dobavljac pronadjiDobavljaca(int id) { session.clear(); session.load(dobavljac, id); return dobavljac;

} }

6. ZaključakRešavajući problem nekompatibilnosti objektne i relacione paradigme (object/relational paradigm mismatch) objektno-relaciono preslikavanje se pokazalo kao najprirodnije

47

Page 48: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

rešenje. Došlo je do “pomirenja” programera koji su krivili relacionu tehnologiju za pomenutu nekompatibilnost paradigmi i profesionalaca iz oblasti relacionih baza koji su za to krivili objektnu tehnologiju.

Otkriveno je više mogućnosti implementacije ovog rešenja, a jedna od njih je i upravo obrađena u ovom radu, Hibernate.

Hibernate je moćan i fleksibilan, ali opet srazmerno jednostavan za upotrebu. Korisniku je omogućeno intuitivno i jednostavno rukovanje perzistentnim podacima na način prikladan objektno orjentisanoj paradigmi, bez potrebe za korišćenjem SQL upita.

On omogućava izuzetno lako podešavanje postavki te definisanje preslikavanja pomoću XML konfiguracionih datoteka. Jednom pravilno podešen, omogućava rukovanje perzistentnim objektima na prirodan način, kako je i predviđeno objektno orjentisanom paradigmom. Perzistentni objekti su podložni minimalnim ograničenjima u pogledu strukture od strane Hibernate-a, što omogućava veliku fleksibilnost sa strane same aplikacije, koja se ne mora prilagođavati komunikaciji sa bazom podataka. Bez obzira na način razvoja aplikacije ili postavljenim zahtevima, Hibernate pravilnom upotrebom može uštedeti mnogo vremena i novca, dajući kodu preglednost, omogućavajući lako održavanje i veliku ponovnu iskoristivost, što su glavne karakteristike svake dobro kodirane aplikacije.

Zahvaljujući svom open-source statusu, kao i širokoj online zajednici, Hibernate se neprestano nadograđuje i širi, razvijajući se u korak s objektnom tehnologijom, te tako predstavlja jedno od najpouzdanijih rešenja za problem perzistentnosti podataka i objektno-relacionog preslikavanja, kako u Javi, tako i u ostalim okruženjima.

7. Literatura

[1] Mike Keith, Merrick Schnicariol: Pro JPA 2 Mastering the Java™ Persistence API,

48

Page 49: Diplom Ski

Realizacija objektno-relacionog preslikavanja u Java okruženju Završni rad

Apress, 2009. [2] Christian Bauer, Gavin King: Java Persistence with Hibernate, Manning Publications, 2007.

[3] Dave Minter, Jeff Linwood: Beginning Hibernate, Apress, 2006.

[4] Željko Gavrilović: Komparativna analiza EJB JPA kontejnerske i JDBC perzitentnosti, master rad, 2008.

[5] Neda Danilović: Komparativna analiza Hibernate I JDBC tehnologija, master rad, 2010.

[6] Rahul Biswas, Ed Ort: The Java Persistence API - A Simpler Programming Model for Entity Persistence, http://www.oracle.com/technetwork/articles/javaee/jpa-137156.html

[7] Hibernate Reference Documentation, http://www.hibernate.org/

49