Hibernate deo 1 NIKOLA AJZENHAMER PROGRAMIRANJE BAZA PODATAKA
Hibernate – deo 1 NIKOLA AJZENHAMER PROGRAMIRANJE BAZA PODATAKA MATEMATIČKI FAKULTET 2019/2020
Uvod u objektno-relaciono preslikavanje (ORP) Konekcija ka bazi podataka Transakcije u Hibernate biblioteci ORP tabela Sadržaj ORP složenih primarnih ključeva Operacije nad jednim ORP slogom ◦ ◦ Unos Čitanje Brisanje Izmena
Uvod u objektno-relaciono preslikavanje (ORP)
Zahtevi pri rešavanju domenskih problema Problem u jeziku domena • • Implementacija poslovne logike u vpj Trajno skladištenje informacija u relacionoj bazi podataka Klase, objekti, poruke. . . Hijerarhije klasa Polimorfizam. . . • Tabele, primarni ključevi, . . . • Integritet i organičenja (strani ključevi, . . . ) • . . .
Alati za ORP Automatsko preslikavanje relacionog modela baze podataka na objektni model aplikacije i obratno Preslikavanje je na neki način odvojeno od razvoja poslovne logike u višem programskom jeziku Implementacija ORP Implementacija poslovne logike u vpj Trajno skladištenje informacija u relacionoj bazi podataka
Hibernate ORM Alat za ORP za programski jezik Java Davalac za JPA (Java Persistence API) ◦ Implementacija specifikacije JPA standarda Idiomatsko trajno skladištenje ◦ Prati prirodne idiome objektno-orijentisane paradigme ◦ Nasleđivanje, polimorfizam, asocijacije, kompozicije, radni okvir za Java kolekcije, . . . Strategije za visoke performanse ◦ Lenje inicijalizacije, brojne strategije za dohvatanje podataka, optimističko zaključavanje, . . . Zvanična veb prezentacija: https: //hibernate. org/orm/ Zvanična dokumentacija: https: //docs. jboss. org/hibernate/orm/5. 4/javadocs/
Konekcija ka bazi podataka
Kreiranje konekcije ka BP / Fabrike sesija Da bi Hibernate radio nad BP, potrebno je da dobije dve vrste informacija: ◦ Podaci za pristupanje BP (url, korisničko ime, lozinka, . . . ) ◦ Podaci o aplikaciji (spisak anotiranih klasa, . . . ) Rezultat pripremne faze Hibernate aplikacija je fabrika sesija koju razvijač može da koristi za pristup podacima nad tom BP Aplikacija obično ima jednu instancu fabrike sesija, koja se koristi za kreiranje potencijalno više objekata sesije Obavezno je na kraju potrebno zatvoriti sve objekte fabrika sesija ◦ void Session. Factory. close() throws Hibernate. Exception
Konfiguraciona XML datoteka Hibernate koristi datoteku hibernate. cfg. xml iz koje se čitaju informacije o konekciji ka BP <? xml version="1. 0" encoding="UTF-8"? > <hibernate-configuration> <session-factory> <property name="connection. url">jdbc: db 2: //localhost: 50001/VSTUD</property> <property name="connection. driver_class">com. ibm. db 2. jcc. DB 2 Driver</property> <property name="connection. username">student</property> <property name="connection. password">abcdef</property> <property name="dialect">org. hibernate. dialect. DB 2 Dialect</property> </session-factory> </hibernate-configuration> Korisničko ime drajvera Vrsta SQL dijalekta za BPkonekciju Lozinka URL za JDBC Naziv JDBC
Kreiranje fabrike sesija 1. Kreirati objekat interfejsa org. hibernate. boot. registry. Standard. Service. Registry : Standard. Service. Registry registry = new Standard. Service. Registry. Builder(). configure(). build(); 2. Proslediti Hibernate biblioteci listu anotiranih entiteta: Metadata. Sources metadata. Sources = new Metadata. Sources(service. Registry); metadata. Sources. add. Annotated. Class(Smer. class); Metadata. Builder metadata. Builder = metadata. Sources. get. Metadata. Builder(); 3. Izgraditi metapodatke: Metadata metadata = metadata. Builder. build(); 4. Kreirati fabriku sesija (objekat interfejsa org. hibernate. Session. Factory): Session. Factory session. Factory = metadata. build. Session. Factory();
Sesije Sve akcije nad BP se izvršavaju u okviru sesija Da bismo mogli da radimo sa BP, potrebno je da otvorimo novu sesiju: ◦ Session. Factory. open. Session() throws Hibernate. Exception Interfejs org. hibernate. Session ◦ Predstavlja glavni interfejs između Java aplikacije i Hibernate biblioteke ◦ Životni vek sesije je usko povezan početkom i krajem logičke transakcije ◦ Primarna uloga je obezbeđivanje metoda za kreiranje, čitanje i brisanje instanci klasa ORP entiteta Obavezno je na kraju potrebno zatvoriti sve objekte sesija ◦ void Session. close() throws Hibernate. Exception
Transakcije u Hibernate biblioteci
Transakcije se u Hibernate biblioteci predstavljaju interfejsom org. hibernate. Transaction Session session = session. Factory. open. Session(); Transaction TR; try { TR = session. begin. Transaction(); //. . . TR. commit(); } catch (Exception e) { if (TR != null) { TR. rollback(); } throw e; } finally { session. close(); } Započinjanje transakcije kreira objekat koji se vezuje za sesiju i traje sve dok se Potvrđivanje izmenailiuponište transakciji: izmene ne potvrde • Izmene u entitetima se trajno upisuju u BP izmena u transakciji • Poništavanje Ako dođe do greške u bilo kod trenutku, ispaljuje se izuzetak tipa Hibernate. Exception (koji nasleđuje Runtime. Exception) Sesija se mora zatvoriti bilo u slučaju uspeha ili neuspeha
ORP tabela
Opšte o ostvarivanju ORP Dva pristupa: ◦ XML datoteke ◦ Java anotacije Mi ćemo koristiti pristup sa Java anotacijama Sve anotacije koje budemo koristili dolaze iz paketa javax. persistence Dokumentacija za anotacije: https: //docs. oracle. com/javaee/7/api/toc. htm
Entiteti Osnovni pojam koji se ne definiše ◦ Značenje je stvar, biće, pojava, dogadaj od značaja, . . . ◦ Može se jednoznačno identifikovati ◦ Može da postoji na različitim nivoima samostalnosti Primeri entiteta u BP VSTUD: student, smer, predmet, ispitni rok, ispit, . . . Kao što primećujemo, entiteti su tabele u BP
Definisanje ORP entiteta Za svaki entitet (tabelu) iz BP, neophodno je: ◦ Kreirati jednu Java klasu ◦ Anotirati tu klasu anotacijom @Entity ◦ Klasa se može anotirati anotacijom @Table čije su važne opcije: ◦ String name – naziv tabele (podr. vred: naziv klase) ◦ String schema – naziv sheme tabele (podr. vred: podrazumevana shema za datog korisnika)
Definisanje ORP entiteta Za svaku kolonu iz odgovarajuće tabele entiteta, neophodno je: ◦ Kreirati jedan atribut u odgovarajućoj Java klasi ◦ Tip atributa mora da odgovara koloni u BP ◦ Atribut se može anotirati anotacijom @Column čije su važne opcije: ◦ String name – naziv kolone (podr. vred: naziv atributa) ◦ boolean unique – da li nad kolonom postoji ograničenje jedinstvenosti (podr. vred: false) ◦ boolean nullable – da li kolona može imati NULL vrednosti (podr. vred: true) Atribut koji predstavlja (jednostavan) primarni ključ mora se anotirati anotacijom @Id
Primer ORP entiteta @Entity @Table(name="KORISNIK_INFO") class Korisnik { @Id @Column(nullable=false) public int iden; KORISNIK_INFO IDEN INTEGER NOT NULL KOR_IME VARCHAR(20) NOT NULL TELEFON VARCHAR(10) @Column(name="KOR_IME", nullable=false, unique=true) public String korisničko. Ime; public String telefon; } PK UNIQUE
ORP složenih primarnih ključeva
Složeni primarni ključevi Primarni ključevi koji se sastoje od više od jedne kolone Primeri u BP VSTUD: ◦ ISPITNI_ROK(GODINA, OZNAKA, . . . ) ◦ ISPIT(INDEKS, GODINA_ROKA, OZNAKA_ROKA, ID_PREDMETA, . . . ) ◦. . . Tri strategije: 1. Korišćenje kombinacije @Embeddable i @Id 2. Korišćenje @Embedded. Id 3. Korišćenje kombinacije @Id. Class i @Id
Primer Tabela KNJIGA sadrži složeni primarni ključ koji se sastoji od narednih kolona: ◦ ◦ ID_GRUPA ID_IZDAVAC ID_NASLOV ID_KONTR_BR KNJIGA ID_GRUPA INTEGER NOT NULL PK ID_IZDAVAC INTEGER NOT NULL PK ID_NASLOV INTEGER NOT NULL PK ID_KONTR_BR INTEGER NOT NULL PK AUTOR VARCHAR(100) NASLOV VARCHAR(100)
Korišćenje kombinacije @Embeddable i @Id Kreirati klasu koja predstavlja PK ◦ Atributi ove klase su kolone koje učestvuju u formiranju PK ◦ Anotirati klasu anotacijom @Embeddable ◦ Klasa implementira interfejs @Embeddable public class ISBN implements Serializable { int id_grupa; int id_izdavac; int id_naslov; int id_kontr_br; java. io. Serializable public ISBN() {} ◦ Klasa ima podrazumevani konstruktor ◦ Klasa prevazilazi metode @Override public boolean equals(Object o) { //. . . } ◦ public boolean equals(Object o) ◦ public int hash. Code() Ovako kreirana klasa se može koristiti kao „ugradljivi“ složeni PK entiteta ◦ Kreira se atribut u entitetu ◦ Anotira se anotacijom @Id @Override public int hash. Code() { //. . . } } @Entity public class Knjiga { @Id ISBN id; String autor; String naslov; }
Korišćenje @Embedded. Id Kreirati klasu koja predstavlja PK ◦ Atributi ove klase su kolone koje učestvuju u formiranju PK ◦ Klasa implementira interfejs java. io. Serializable public class ISBN implements Serializable { int id_grupa; int id_izdavac; int id_naslov; int id_kontr_br; @Entity public class Knjiga { @Embedded. Id ISBN id; String autor; String naslov; } public ISBN() {} ◦ Klasa ima podrazumevani konstruktor ◦ Klasa prevazilazi metode @Override public boolean equals(Object o) { //. . . } ◦ public boolean equals(Object o) ◦ public int hash. Code() Ovako kreirana klasa se može koristiti kao „ugrađeni“ složeni PK entiteta @Override public int hash. Code() { //. . . } ◦ Kreira se atribut u entitetu ◦ Anotira se anotacijom @Embedded. Id }
Korišćenje kombinacije @Id. Class i @Id Kreirati klasu koja predstavlja PK ◦ Atributi ove klase su kolone koje učestvuju u formiranju PK ◦ Klasa implementira interfejs java. io. Serializable public class ISBN implements Serializable { int id_grupa; int id_izdavac; int id_naslov; int id_kontr_br; ◦ Klasa ima podrazumevani konstruktor ◦ Klasa prevazilazi metode public ISBN() {} ◦ public boolean equals(Object o) ◦ public int hash. Code() @Override public boolean equals(Object o) { //. . . } Ovako kreirana klasa se može koristiti kao složeni PK entiteta ◦ Entitet se anotira anotacijom @Id. Class čija je vrednost tip klase koja predstavlja PK ◦ Odgovarajući atributi ove klase su kolone koje učestvuju u formiranju PK ◦ Svaki takav atribut se anotira anotacijom @Id @Entity @Id. Class(ISBN. class) public class Knjiga { @Id int id_grupa; @Id int id_izdavac; @Id int id_naslov; @Id int id_kontr_br; String autor; String naslov; } @Override public int hash. Code() { //. . . } }
Napomene Prva strategija se najčešće koristi, zatim druga i treća najređe Ukoliko želimo da se PK jedne klase koristi kao deo neke druge klase, onda je neophodno da koristimo prvu strategiju ◦ Samo „ugradljivi“ PK mogu biti deo drugih klasa Primer iz BP VSTUD: PK klase entiteta ispitni rok učestvuje kao deo PK klase entiteta ispita ◦ Kreiramo klasu Ispitni. Rok. Id koja predstavlja PK klase entiteta ispitni rok @Embeddable class Ispitni. Rok. Id implements Serializable { int godina; String oznaka; /*. . . */ } ◦ Kreiramo klasu Ispit. Id koja predstavlja PK klase entiteta ispit class Ispit. Id implements Serializable { Ispitni. Rok. Id ir; int indeks; int id_predmeta; /*. . . */ } Zbog toga što se Ispitni. Rok. Id koristi kao deo druge klase, on mora biti implementiran pomoću prve strategije
Operacije nad jednim ORP slogom
Unos Novi slog se unosi u BP pomoću naredne procedure: 1. Kreira se novi objekat odgovarajuće klase entiteta ◦ Eventualno, potrebno je kreirati objekat PK ako je PK složeni 2. Postavljaju se vrednosti atributa klase 3. Poziva se metod Serializable Session. save(Object object) ◦ Argument object je novokreirani objekat 4. Potvrđuje se transakcija ISBN pk = new ISBN(. . . ); Knjiga obj = new Knjiga(pk); obj. set. Autor(. . . ); obj. set. Naslov(. . . ); session. save(obj); TR. commit();
Čitanje sloga iz BP na osnovu datog PK vrši se pomoću naredne procedure: 1. Kreira se novi objekat PK 2. Kreira se prazna instanca odgovarajuće klase entiteta 3. Poziva se neki od dva metoda za dohvatanje sloga iz narednih familija metoda: ◦ Familija metoda load() pretpostavlja da slog sa datim PK postoji u BP. Inače, ispaljuje se izuzetak. ◦ Familija metoda get() pokušava da dohvati slog sa datim PK iz BP. Ako ne uspe, vraća null. 4. Prazna instanca je popunjena pročitanim slogom i može se koristiti regularno u slučaju da nije došlo do greške ISBN pk = new ISBN(. . . ); Knjiga obj = new Knjiga(); try { session. load(obj, pk); } catch (Exception e) { System. out. println("Ne postoji!"); return; } // ili. . . obj = session. get(Knjiga. class, pk); if (null == obj) { System. out. println("Ne postoji!"); return; } String autor = obj. get. Autor(); String naslov = obj. get. Naslov();
Brisanje sloga iz BP vrši se pomoću naredne procedure: 1. Izračunava se objekat koji odgovara slogu koji će biti obrisan 2. Poziva se metod void Session. delete(Object object) ◦ Argument object je instanca objekta (sloga) koji se briše 3. Potvrđuje se transakcija ISBN pk = new ISBN(. . . ); Knjiga obj = session. get(Knjiga. class, pk); if (null == obj) { System. out. println("Ne postoji!"); return; } session. delete(obj); TR. commit();
Izmena sloga iz BP vrši se pomoću naredne procedure: 1. Izračunava se objekat koji odgovara slogu koji će biti izmenjen 2. Vrši se izmena atributa na nivou tog objekta na način koji odgovara željenoj izmeni 3. Potvrđuje se transakcija ISBN pk = new ISBN(. . . ); Knjiga obj = session. get(Knjiga. class, pk); if (null == obj) { System. out. println("Ne postoji!"); return; } obj. set. Autor("Brandon Sanderson"); obj. set. Naslov("The Final Empire"); TR. commit();
Hvala na pažnji! NIKOLA AJZENHAMER PROGRAMIRANJE BAZA PODATAKA MATEMATIČKI FAKULTET 2019/2020
- Slides: 32