Det er godt å forstå behovet for objekt- / relasjonskartlegging (ORM) i Java-applikasjoner, men du er sannsynligvis ivrig etter å se dvalemodus i aksjon. Vi begynner med å vise deg et enkelt eksempel som viser noe av kraften.
Som du sikkert er klar over, er det tradisjonelt at en programmeringsbok begynner med et "Hello World" -eksempel. I dette kapittelet følger vi den tradisjonen ved å introdusere Hibernate med et relativt enkelt "Hello World" -program. Men bare å skrive ut en melding til et konsollvindu vil ikke være nok til å virkelig demonstrere dvalemodus. I stedet lagrer programmet nyopprettede objekter i databasen, oppdaterer dem og utfører spørsmål for å hente dem fra databasen.
I tillegg til det kanoniske "Hello World" -eksemplet introduserer vi kjernen Hibernate API-er og gir detaljer for en grunnleggende konfigurasjon.
"Hello World" med dvalemodus
Dvalemodusapplikasjoner definerer vedvarende klasser som er "kartlagt" til databasetabeller. Eksemplet vårt "Hello World" består av en klasse og en kartleggingsfil. La oss se hvordan en enkel vedvarende klasse ser ut, hvordan kartleggingen er spesifisert, og noen av tingene vi kan gjøre med forekomster av den vedvarende klassen som bruker dvalemodus.
Målet med prøveeksemplet vårt er å lagre meldinger i en database og å hente dem for visning. Søknaden har en enkel vedvarende klasse, Beskjed
, som representerer disse utskrivbare meldingene. Våre Beskjed
klasse vises i oppføring 1.
Oppføring 1. Message.java: En enkel vedvarende klasse
pakke hei; offentlig klasse Melding {privat Lang id; privat strengtekst; privat melding nextMessage; privat melding () {} offentlig melding (strengtekst) {this.text = tekst; } offentlig Lang getId () {retur id; } privat ugyldig setId (lang id) {this.id = id; } offentlig streng getText () {returtekst; } public void setText (String text) {this.text = text; } offentlig melding getNextMessage () {return nextMessage; } public void setNextMessage (Message nextMessage) {this.nextMessage = nextMessage; }}
Våre Beskjed
klasse har tre attributter: identifikatorattributtet, teksten til meldingen og en referanse til en annen Beskjed
. Identifikatorattributtet gir applikasjonen tilgang til databaseidentiteten - den primære nøkkelverdien - til et vedvarende objekt. Hvis to tilfeller av Beskjed
har samme identifikasjonsverdi, representerer de samme rad i databasen. Vi har valgt Lang
for typen identifikatorattributt, men dette er ikke et krav. Dvalemodus tillater praktisk talt alt for identifikasjonstypen, som du vil se senere.
Du har kanskje lagt merke til at alle attributtene til Beskjed
klasse har metoder for tilgang til JavaBean-stil. Klassen har også en konstruktør uten parametere. De vedvarende klassene vi bruker i eksemplene våre, vil nesten alltid se ut som dette.
Forekomster av Beskjed
klasse kan administreres (gjøres vedvarende) av dvalemodus, men de gjør det ikke ha å være. Siden Beskjed
objektet implementerer ingen dvalespesifikke klasser eller grensesnitt, vi kan bruke det som alle andre Java-klasser:
Meldingsmelding = ny melding ("Hello World"); System.out.println (message.getText ());
Dette kodefragmentet gjør akkurat det vi har forventet fra "Hello World" -applikasjoner: Den skrives ut "Hei Verden"
til konsollen. Det kan se ut som om vi prøver å være søte her; faktisk demonstrerer vi en viktig funksjon som skiller dvalemodus fra noen andre utholdenhetsløsninger, for eksempel EJB (Enterprise JavaBean) enhetsbønner. Vår vedvarende klasse kan brukes i hvilken som helst utførelsessammenheng - ingen spesiell container er nødvendig. Selvfølgelig kom du hit for å se dvalemodus selv, så la oss lagre en ny Beskjed
til databasen:
Sessionsøkt = getSessionFactory (). OpenSession (); Transaksjon tx = session.beginTransaction (); Meldingsmelding = ny melding ("Hello World"); session.save (melding); tx.commit (); session.close ();
Denne koden kaller dvalemodus Økt
og Transaksjon
grensesnitt. (Vi kommer til det getSessionFactory ()
ring snart.) Det resulterer i kjøring av noe som ligner på følgende SQL:
sett inn i MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) verdier (1, 'Hello World', null)
Vent - den MESSAGE_ID
kolonnen initialiseres til en merkelig verdi. Vi satte ikke inn id
tilhører beskjed
hvor som helst, så vi forventer at det skal være null
, Ikke sant? Egentlig, den id
eiendommen er spesiell: Det er en identifikasjonsegenskap—Det har en generert unik verdi. (Vi diskuterer hvordan verdien genereres senere.) Verdien tildeles til Beskjed
instans av dvalemodus når lagre()
er kalt.
For dette eksemplet antar vi at MELDINGER
tabellen eksisterer allerede. Selvfølgelig ønsker vi at "Hello World" -programmet vårt skal skrive ut meldingen til konsollen. Nå som vi har en melding i databasen, er vi klare til å demonstrere dette. Det neste eksemplet henter alle meldinger fra databasen, i alfabetisk rekkefølge, og skriver dem ut:
Session newSession = getSessionFactory (). OpenSession (); Transaksjon newTransaction = newSession.beginTransaction (); Listemeldinger = newSession.find ("fra Melding som m rekkefølge etter m.text asc"); System.out.println (meldinger.størrelse () + "melding (er) funnet:"); for (Iterator iter = messages.iterator (); iter.hasNext ();) {Message message = (Message) iter.next (); System.out.println (message.getText ()); } newTransaction.commit (); newSession.close ();
Den bokstavelige strengen "fra melding som m rekkefølge etter m.text asc"
er en Hibernate-spørring, uttrykt i Hibernates eget objektorienterte Hibernate Query Language (HQL). Dette spørsmålet oversettes internt til følgende SQL når finne()
er kalt:
velg m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID fra MESSAGES m rekkefølge etter m.MESSAGE_TEXT asc
Kodefragmentet skrives ut:
1 melding (er) funnet: Hello World
Hvis du aldri har brukt et ORM-verktøy som Hibernate før, forventet du sannsynligvis å se SQL-setningene et sted i koden eller metadataene. De er ikke der. All SQL genereres ved kjøretid (faktisk ved oppstart, for alle gjenbrukbare SQL-setninger).
For å la denne magien oppstå, trenger dvalemodus mer informasjon om hvordan Beskjed
klassen skal gjøres vedvarende. Denne informasjonen er vanligvis gitt i en XML-kartleggingsdokument. Kartleggingsdokumentet definerer blant annet hvordan egenskaper til Beskjed
klassekart til kolonner i MELDINGER
bord. La oss se på kartleggingsdokumentet i Oppføring 2.
Oppføring 2. En enkel dvalemodus XML-kartlegging
Kartleggingsdokumentet forteller dvalemodus at Beskjed
klassen skal holdes fast til MELDINGER
tabellen, at identifikasjonsegenskapen tilordnes til en kolonne som heter MESSAGE_ID
, at tekstegenskapen tilordnes til en kolonne som heter MESSAGE_TEXT
, og at eiendommen navngitt neste Melding
er en tilknytning til mange-til-en-mangfold som tilordnes til en kolonne som heter NESTE_MESSAGE_ID
. (Ikke bekymre deg for de andre detaljene foreløpig.)
Som du kan se, er ikke XML-dokumentet vanskelig å forstå. Du kan enkelt skrive og vedlikeholde den for hånd. Uansett hvilken metode du velger, har dvalemodus nok informasjon til å generere alle SQL-setningene som trengs for å sette inn, oppdatere, slette og hente forekomster av Beskjed
klasse. Du trenger ikke lenger å skrive disse SQL-setningene for hånd.
Merk |
---|
Mange Java-utviklere har klaget på "metadatahelvetet" som følger J2EE-utviklingen. Noen har foreslått en bevegelse fra XML-metadata tilbake til vanlig Java-kode. Selv om vi applauderer dette forslaget for noen problemer, representerer ORM et tilfelle der tekstbaserte metadata virkelig er nødvendig. Dvalemodus har fornuftige standarder som minimerer skriving og en moden dokumenttypedefinisjon som kan brukes til automatisk fullføring eller validering i redaktører. Du kan til og med automatisk generere metadata med forskjellige verktøy. |
La oss nå endre vår første melding, og mens vi er i gang, oppretter du en ny melding tilknyttet den første, som vist i liste 3.
Oppføring 3. Oppdatere en melding
Sessionsøkt = getSessionFactory (). OpenSession (); Transaksjon tx = session.beginTransaction (); // 1 er den genererte ID-en til den første meldingen Message message = (Message) session.load (Message.class, new Long (1)); message.setText ("Hilsen Earthling"); Melding nextMessage = ny melding ("Ta meg til lederen din (vær så snill)"); message.setNextMessage (nextMessage); tx.commit (); session.close ();
Denne koden kaller tre SQL-setninger i samme transaksjon:
velg m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID fra MESSAGES m hvor m.MESSAGE_ID = 1 sett inn i MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) verdier (2, 'Ta meg til lederen din (vær så snill)', null) oppdater MESSAGES sett MESSAGE_TEXT = 'Hilsen Earthling', NEXT_MESSAGE_ID = 2 hvor MESSAGE_ID = 1
Legg merke til hvordan dvalemodus oppdaget endringen til tekst
og neste Melding
egenskapene til den første meldingen og automatisk oppdatert databasen. Vi har utnyttet en dvalemodus-funksjon som heter automatisk skittenkontroll: denne funksjonen sparer oss for å eksplisitt be dvalemodus om å oppdatere databasen når vi endrer tilstanden til et objekt i en transaksjon. På samme måte kan du se at den nye meldingen ble gjort vedvarende da en referanse ble opprettet fra den første meldingen. Denne funksjonen kalles cascading lagre: det sparer oss for å eksplisitt gjøre det nye objektet vedvarende ved å ringe lagre()
, så lenge det kan nås ved en allerede vedvarende forekomst. Legg også merke til at bestillingen av SQL-setningene ikke er den samme som rekkefølgen vi setter eiendomsverdier i. Dvalemodus bruker en sofistikert algoritme for å bestemme en effektiv ordre som unngår databrudd på fremmednøkkelbegrensninger i databasen, men som fortsatt er tilstrekkelig forutsigbar for brukeren. Denne funksjonen kalles transaksjonell nedskrivning.
Hvis vi kjører "Hello World" igjen, skrives det ut:
2 meldinger funnet: Hilsen Earthling Ta meg til lederen din (vær så snill)
Dette er så langt vi tar "Hello World" -applikasjonen. Nå som vi endelig har litt kode under beltet, tar vi et skritt tilbake og presenterer en oversikt over Hibernates viktigste API-er.
Å forstå arkitekturen
Programmeringsgrensesnittene er det første du må lære om dvalemodus for å bruke det i utholdenhetslaget i applikasjonen. Et hovedmål med API-design er å holde grensesnittene mellom programvarekomponenter så smale som mulig. I praksis er ORM API-er imidlertid ikke spesielt små. Ikke bekymre deg, skjønt; du trenger ikke å forstå alle dvalemodusgrensesnittene på en gang. Figuren nedenfor illustrerer rollene til de viktigste dvalemodusgrensesnittene i forretnings- og utholdenhetslagene.
Vi viser virksomhetslaget over utholdenhetslaget, siden virksomhetslaget fungerer som en klient av utholdenhetslaget i et tradisjonelt lagdelt program. Merk at noen enkle applikasjoner kanskje ikke skiller forretningslogikk fra persistenslogikk rent; det er greit - det forenkler bare diagrammet.
Dvalemodusgrensesnittene vist i figuren ovenfor kan omtrent klassifiseres som følger:
- Grensesnitt som kalles av applikasjoner for å utføre grunnleggende CRUD (opprette / lese / oppdatere / slette) og spørringsoperasjoner. Disse grensesnittene er hovedavhengigheten av applikasjonsvirksomhet / kontrolllogikk i dvalemodus. De inkluderer
Økt
,Transaksjon
, ogSpørsmål
. - Grensesnitt kalt av applikasjonsinfrastrukturkode for å konfigurere dvalemodus, viktigst av alt,
Konfigurasjon
klasse. - Ring tilbake grensesnitt som lar applikasjonen reagere på hendelser som forekommer i dvalemodus, for eksempel
Interceptor
,Livssyklus
, ogValiderbar
. - Grensesnitt som tillater utvidelse av Hibernates kraftige kartfunksjonalitet, for eksempel
Brukertype
,CompositeUserType
, ogIdentifierGenerator
. Disse grensesnittene er implementert med applikasjonsinfrastrukturkode (om nødvendig).
Hibernate bruker eksisterende Java API-er, inkludert JDBC (Java Database Connectivity), Java Transaction API (JTA) og Java Naming and Directory Interface (JNDI). JDBC gir et rudimentært nivå av abstraksjon av funksjonalitet som er felles for relasjonsdatabaser, slik at nesten alle databaser med en JDBC-driver kan støttes av dvalemodus. JNDI og JTA lar Hibernate integreres med J2EE applikasjonsservere.
I denne delen dekker vi ikke den detaljerte semantikken til Hibernate API-metoder, bare rollen til hvert av de primære grensesnittene. Du finner de fleste av disse grensesnittene i pakken net.sf. dvale
. La oss ta en kort titt på hvert grensesnitt etter tur.
Kjernegrensesnittene
De fem kjernegrensesnittene brukes i omtrent alle dvalemodusapplikasjoner. Ved å bruke disse grensesnittene kan du lagre og hente vedvarende objekter og kontrollere transaksjoner.
Sessionsgrensesnitt