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
, inPoizvedba
. - 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
, inPreverljivo
. - Vmesniki, ki omogočajo razširitev zmogljive funkcije preslikave Hibernate, kot je
UserType
,CompositeUserType
, inIdentifierGenerator
. 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