Programiranje

Začnite uporabljati Hibernate

Dobro je razumeti potrebo po objektnem / relacijskem preslikavanju (ORM) v aplikacijah Java, vendar si verjetno želite videti Hibernate v akciji. Za začetek vam bomo pokazali preprost primer, ki dokazuje nekaj njegove moči.

Kot verjetno veste, je običajno, da se programska knjiga začne s primerom "Hello World". V tem poglavju sledimo tej tradiciji z uvedbo hibernacije s sorazmerno preprostim programom "Hello World". Vendar preprosto tiskanje sporočila v okno konzole ne bo dovolj za resnično predstavitev stanja mirovanja. Namesto tega bo naš program shranil novo ustvarjene predmete v bazo podatkov, jih posodobil in izvede poizvedbe za njihovo pridobivanje iz baze podatkov.

Poleg kanoničnega primera "Hello World" predstavljamo tudi osnovne API-je hibernacije in podajamo podrobnosti za osnovno konfiguracijo.

"Pozdravljeni svet" s hibernacijo

Aplikacije za mirovanje definirajo trajne razrede, ki so "preslikani" v tabele baz podatkov. Naš primer "Hello World" je sestavljen iz enega razreda in ene preslikavne datoteke. Poglejmo, kako izgleda preprost trajni razred, kako je določeno preslikavanje in nekatere stvari, ki jih lahko naredimo s primerki trajnega razreda z uporabo hibernacije.

Cilj naše vzorčne aplikacije je shraniti sporočila v bazo podatkov in jih pridobiti za prikaz. Aplikacija ima preprost vztrajen razred, Sporočilo, ki predstavlja ta sporočila za tiskanje. Naše Sporočilo razred je prikazan na seznamu 1.

Seznam 1. Message.java: Preprost trajni razred

paket pozdrav; sporočilo javnega razreda {private Long id; besedilo zasebnega niza; zasebno sporočilo nextMessage; zasebno sporočilo () {} javno sporočilo (besedilo v nizu) {this.text = text; } public Long getId () {return id; } private void setId (Long id) {this.id = id; } javni String getText () {vrnitev besedila; } javna void setText (besedilo v nizu) {this.text = text; } javno sporočilo getNextMessage () {return nextMessage; } javna void setNextMessage (Sporočilo nextMessage) {this.nextMessage = nextMessage; }} 

Naše Sporočilo class ima tri atribute: atribut identifikator, besedilo sporočila in sklic na drugega Sporočilo. Atribut identifikator omogoča aplikaciji dostop do identitete baze podatkov - vrednosti primarnega ključa - trajnega predmeta. Če sta dva primera Sporočilo imajo enako vrednost identifikatorja, predstavljajo isto vrstico v bazi podatkov. Izbrali smo dolga za tip našega atributa identifikatorja, vendar to ni zahteva. Hibernate omogoča skoraj vse za vrsto identifikatorja, kot boste videli kasneje.

Morda ste opazili, da so vsi atributi Sporočilo razreda imajo metode dostopa do lastnosti v slogu JavaBean. Razred ima tudi konstruktor brez parametrov. Vztrajni razredi, ki jih uporabljamo v svojih primerih, bodo skoraj vedno videti nekako tako.

Primeri Sporočilo razreda lahko Hibernate upravlja (postane trajen), vendar ne imeti biti. Ker je Sporočilo object ne izvaja nobenih razredov ali vmesnikov, specifičnih za Hibernate, lahko ga uporabljamo kot kateri koli drug razred Java:

Sporočilo sporočila = novo sporočilo ("Hello World"); System.out.println (message.getText ()); 

Ta fragment kode naredi točno tisto, kar smo pričakovali od aplikacij "Hello World": natisne "Pozdravljen, svet" na konzolo. Morda se zdi, da se tu trudimo biti luštni; pravzaprav prikazujemo pomembno funkcijo, ki Hibernate razlikuje od nekaterih drugih rešitev obstojnosti, kot je fižol entitet EJB (Enterprise JavaBean). Naš trajni razred lahko uporabimo v katerem koli kontekstu izvajanja - poseben vsebnik ni potreben. Seveda ste prišli sem pogledat sam Hibernate, zato shranimo novega Sporočilo v zbirko podatkov:

Seja seje = getSessionFactory (). OpenSession (); Transakcija tx = session.beginTransaction (); Sporočilo sporočila = novo sporočilo ("Hello World"); session.save (sporočilo); tx.commit (); session.close (); 

Ta koda imenuje mirovanje Seja in Transakcija vmesniki. (Do tega bomo prišli getSessionFactory () pokličite kmalu.) Rezultat je izvedba nečesa podobnega naslednjemu SQL:

vstavi v vrednosti MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) (1, 'Hello World', null) 

Počakaj - MESSAGE_ID stolpec se inicializira na čudno vrednost. Nismo nastavili id lastnina sporočilo kjerkoli, zato bi pričakovali, da bo nič, prav? Pravzaprav id lastnost je posebna: to je lastnost identifikatorja—Drži ustvarjeno edinstveno vrednost. (O tem, kako se vrednost ustvari, bomo razpravljali pozneje.) Vrednost je dodeljena Sporočilo primer Hibernate, ko shrani () je poklican.

Za ta primer predpostavljamo, da SPOROČILA tabela že obstaja. Seveda želimo, da program "Hello World" natisne sporočilo na konzolo. Zdaj, ko imamo v bazi sporočilo, smo to pripravljeni pokazati. Naslednji primer pridobi vsa sporočila iz baze podatkov po abecednem vrstnem redu in jih natisne:

Seja newSession = getSessionFactory (). OpenSession (); Transakcija newTransaction = newSession.beginTransaction (); Seznam sporočil = newSession.find ("od Sporočilo kot m razvrsti po m.text asc"); System.out.println (messages.size () + "najdena sporočila:"); for (Iterator iter = messages.iterator (); iter.hasNext ();) {Message message = (Message) iter.next (); System.out.println (message.getText ()); } newTransaction.commit (); newSession.close (); 

Dobesedni niz "iz sporočila kot m vrstni red m.text asc" je poizvedba Hibernate, izražena v lastnem objektno usmerjenem Hibernate Query Language (HQL) Hibernate. Ta poizvedba se interno prevede v naslednji SQL, ko najti() je poklican:

izberite m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID med MESSAGES m vrstni red po m.MESSAGE_TEXT asc 

Natisne se fragment kode:

Najdeno 1 sporočil: Hello World 

Če še nikoli niste uporabljali orodja ORM, kot je Hibernate, ste verjetno pričakovali, da boste stavke SQL videli nekje v kodi ali metapodatkih. Niso tam. Ves SQL se ustvari med izvajanjem (pravzaprav ob zagonu, za vse stavke SQL za večkratno uporabo).

Da bi omogočil to čarovništvo, Hibernate potrebuje več informacij o tem, kako Sporočilo razred naj bo vztrajen. Te informacije so običajno na voljo v Dokument za preslikavo XML. Dokument za preslikavo med drugim določa, kako lastnosti datoteke Sporočilo zemljevid razreda v stolpce SPOROČILA tabela. Oglejmo si dokument za preslikavo v seznamu 2.

Seznam 2. Enostavno preslikavanje hibernacije XML

Dokument za preslikavo hibernaciji sporoča, da Sporočilo razred je treba vztrajati na SPOROČILA tabela, ki jo lastnost identifikatorja preslika v stolpec z imenom MESSAGE_ID, da se lastnost besedila preslika v stolpec z imenom MESSAGE_TEXT, in da je nepremičnina z imenom nextMessage je povezava z mnogokratnost večkratnosti ki preslika v stolpec z imenom NEXT_MESSAGE_ID. (Za zdaj ne skrbite zaradi drugih podrobnosti.)

Kot lahko vidite, dokumenta XML ni težko razumeti. Z lahkoto lahko pišete in vzdržujete ročno. Katero koli metodo izberete, ima Hibernate dovolj informacij za popolno generiranje vseh stavkov SQL, ki bi bili potrebni za vstavljanje, posodabljanje, brisanje in pridobivanje primerkov datoteke Sporočilo razred. Teh stavkov SQL ni treba več pisati ročno.

Opomba
Številni razvijalci Java so se pritoževali nad "peklom metapodatkov", ki spremlja razvoj J2EE. Nekateri predlagajo odmik od metapodatkov XML nazaj k navadni kodi Java. Čeprav za nekaj težav pozdravljamo ta predlog, ORM predstavlja primer, ko so metapodatki na podlagi besedila resnično potrebni. Hibernate ima smiselne privzete nastavitve, ki zmanjšujejo tipkanje, in definicijo zrelega tipa dokumenta, ki se lahko uporablja za samodejno dokončanje ali preverjanje veljavnosti v urejevalnikih. Z različnimi orodji lahko celo samodejno generirate metapodatke.

Zdaj pa spremenimo svoje prvo sporočilo in, ko smo že pri tem, ustvarimo novo sporočilo, povezano s prvim, kot je prikazano v seznamu 3.

Seznam 3. Posodabljanje sporočila

Seja seje = getSessionFactory (). OpenSession (); Transakcija tx = session.beginTransaction (); // 1 je generirani id prvega sporočila Sporočilo sporočilo = (Sporočilo) session.load (Message.class, novo Long (1)); message.setText ("Lep pozdrav Zemljan"); Message nextMessage = novo sporočilo ("Peljite me k svojemu vodji (prosim)"); message.setNextMessage (nextMessage); tx.commit (); session.close (); 

Ta koda pokliče tri stavke SQL znotraj iste transakcije:

izberite m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID iz MESSAGES m, kjer m.MESSAGE_ID = 1 vstavi v MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) vrednosti (2, 'Vodi me do svojega vodje (prosim)', null) posodobi MAGES nastavite MESSAGE_TEXT = 'Lep pozdrav Zemljan', NEXT_MESSAGE_ID = 2, kjer je MESSAGE_ID = 1 

Opazite, kako je Hibernate zaznal spremembo besedilo in nextMessage lastnosti prvega sporočila in samodejno posodobil bazo podatkov. Izkoristili smo funkcijo hibernacije, imenovano samodejno preverjanje umazanije: ta funkcija nam prihrani trud, da Hibernate izrecno prosimo, da posodobi bazo podatkov, ko spremenimo stanje predmeta znotraj transakcije. Podobno lahko vidite, da je bilo novo sporočilo obstojno, ko je bila referenca ustvarjena iz prvega sporočila. Ta funkcija se imenuje kaskadno shrani: prihrani nam napor, da s klicem izrecno naredimo nov predmet obstojnim shrani (), če je dosegljiv že obstojnemu primerku. Upoštevajte tudi, da vrstni red stavkov SQL ni enak vrstnemu redu, v katerem smo nastavili vrednosti lastnosti. Hibernate s pomočjo izpopolnjenega algoritma določi učinkovito naročanje, s katerim se izogne ​​kršitvam omejitev tujega ključa baze podatkov, vendar je še vedno dovolj predvidljivo za uporabnika. Ta funkcija se imenuje transakcijsko zaostajanje.

Če znova zaženemo "Hello World", se natisne:

Najdeno 2 sporočila: Pozdravi Zemljani Peljite me k svojemu vodji (prosim) 

To je, kolikor bomo uporabili aplikacijo "Hello World". Zdaj, ko imamo končno nekaj kode, bomo stopili korak nazaj in predstavili pregled glavnih API-jev Hibernate.

Razumevanje arhitekture

Programski vmesniki so prva stvar, ki se jo morate naučiti o načinu mirovanja, da ga lahko uporabite v trajnem sloju aplikacije. Glavni cilj oblikovanja API je ohraniti čim bolj ozke vmesnike med komponentami programske opreme. V praksi pa API-ji ORM niso posebej majhni. Ne skrbite pa; vam ni treba razumeti vseh vmesnikov Hibernate hkrati. Spodnja slika prikazuje vlogo najpomembnejših vmesnikov Hibernate v poslovnem in vztrajnem sloju.

Prikazujemo poslovno plast nad plastjo obstojnosti, saj ta deluje kot odjemalec obstojnosti v tradicionalno večplastni aplikaciji. Upoštevajte, da nekatere preproste aplikacije morda ne bodo povsem ločile poslovne logike od logike obstojnosti; to je v redu - samo poenostavi diagram.

Hibernate vmesnike, prikazane na zgornji sliki, lahko približno razvrstimo na naslednji način:

  • Vmesniki, ki jih aplikacije pokličejo za izvajanje osnovnih CRUD (ustvarjanje / branje / posodabljanje / brisanje) in poizvedbo. Ti vmesniki so glavna točka odvisnosti poslovne / nadzorne logike aplikacij od stanja mirovanja. Vključujejo Seja, Transakcija, in Poizvedba.
  • Vmesniki, ki jih koda aplikacijske infrastrukture pokliče za konfiguracijo hibernacije, kar je najpomembneje, Konfiguracija razred.
  • Poklicati nazaj vmesniki, ki omogočajo aplikaciji, da se odzove na dogodke, ki se zgodijo v stanju mirovanja, kot je Prestreznik, Življenski krog, in Preverljivo.
  • Vmesniki, ki omogočajo razširitev zmogljive funkcije preslikave Hibernate, kot je UserType, CompositeUserType, in IdentifierGenerator. Ti vmesniki se izvajajo s kodo infrastrukture aplikacije (če je potrebno).

Hibernate uporablja obstoječe Java API-je, vključno z JDBC (Java Database Connectivity), Java Transaction API (JTA) in Java Naming and Directory Interface (JNDI). JDBC zagotavlja osnovno raven abstrakcije funkcionalnosti, ki je skupna relacijskim bazam podatkov, kar omogoča, da Hibernate podpira skoraj vsako bazo podatkov z gonilnikom JDBC. JNDI in JTA omogočata, da se Hibernate integrira s strežniki aplikacij J2EE.

V tem razdelku ne pokrivamo podrobne semantike metod Hibernate API, temveč le vlogo vsakega od primarnih vmesnikov. Večino teh vmesnikov najdete v paketu net.sf.hibernate. Oglejmo si na kratko vsak vmesnik po vrsti.

Jedrni vmesniki

Pet osnovnih vmesnikov se uporablja v skoraj vsaki aplikaciji Hibernate. Z uporabo teh vmesnikov lahko shranjujete in pridobivate trajne predmete in nadzorujete transakcije.

Vmesnik seje

$config[zx-auto] not found$config[zx-overlay] not found