Java Persistence API (JPA) er en Java-spesifikasjon som bygger bro mellom relasjonsdatabaser og objektorientert programmering. Denne todelte opplæringen introduserer JPA og forklarer hvordan Java-objekter er modellert som JPA-enheter, hvordan enhetsforhold er definert, og hvordan du bruker JPAs EntityManager
med lagringsmønsteret i Java-applikasjonene dine.
Merk at denne veiledningen bruker dvalemodus som JPA-leverandør. De fleste konsepter kan utvides til andre Java-utholdenhetsrammer.
Hva er JPA?
Se "Hva er JPA? Introduksjon til Java Persistence API" for å lære om utviklingen av JPA og relaterte rammer, inkludert EJB 3.0. og JDBC.
Objektrelasjoner i JPA
Relasjonsdatabaser har eksistert som et middel for lagring av programdata siden 1970-tallet. Mens utviklere i dag har mange alternativer til relasjonsdatabasen, er denne typen databaser skalerbar og godt forstått, og brukes fortsatt mye i små og store programvareutviklinger.
Java-objekter i en relasjonell databasekontekst er definert som enheter. Enheter plasseres i tabeller der de opptar kolonner og rader. Programmører bruker utenlandske nøkler og bli med på bord å definere forholdet mellom enheter - nemlig en-til-en, en-til-mange og mange-til-mange relasjoner. Vi kan også bruke SQL (Structured Query Language) for å hente og samhandle med data i individuelle tabeller og på tvers av flere tabeller ved hjelp av begrensninger for utenlandske nøkler. Relasjonsmodellen er flat, men utviklere kan skrive spørsmål for å hente data og konstruere objekter fra disse dataene.
Objekt-relasjoner impedans mismatch
Du kan være kjent med begrepet objekt-relasjoner impedans mismatch, som refererer til utfordringen med å kartlegge dataobjekter til en relasjonsdatabase. Denne uoverensstemmelsen oppstår fordi objektorientert design ikke er begrenset til en-til-en, en-til-mange og mange-til-mange relasjoner. I stedet, i objektorientert design, tenker vi på objekter, deres attributter og oppførsel, og hvordan objekter forholder seg. To eksempler er innkapsling og arv:
- Hvis et objekt inneholder et annet objekt, definerer vi dette gjennom innkapsling--en har en forhold.
- Hvis et objekt er en spesialisering av et annet objekt, definerer vi dette gjennom arv- en er en forhold.
Assosiasjon, aggregering, komposisjon, abstraksjon, generalisering, realisering og avhengigheter er alle objektorienterte programmeringskonsepter som kan være utfordrende å kartlegge til en relasjonsmodell.
ORM: Objektrelasjonell kartlegging
Misforholdet mellom objektorientert design og relasjonell databasemodellering har ført til en klasse verktøy utviklet spesielt for objektrelasjonell kartlegging (ORM). ORM-verktøy som Hibernate, EclipseLink og iBatis oversetter relasjonsdatabasemodeller, inkludert enheter og deres forhold, til objektorienterte modeller. Mange av disse verktøyene eksisterte før JPA-spesifikasjonen, men uten standard var funksjonene deres avhengig av leverandør.
Java Persistence API (JPA) ble først utgitt som en del av EJB 3.0 i 2006, og tilbyr en standard måte å kommentere objekter slik at de kan kartlegges og lagres i en relasjonsdatabase. Spesifikasjonen definerer også en felles konstruksjon for samhandling med databaser. Å ha en ORM-standard for Java gir konsistens i leverandørimplementeringer, samtidig som det gir mulighet for fleksibilitet og tillegg. Som et eksempel, mens den originale JPA-spesifikasjonen gjelder for relasjonsdatabaser, har noen leverandørimplementeringer utvidet JPA for bruk med NoSQL-databaser.
Utvikling av JPA
Den første utgivelsen av JPA, versjon 1.0, ble utgitt i 2006 gjennom Java Community Process (JCP) som Java Specification Request (JSR) 220. Versjon 2.0 (JSR 317) ble publisert i 2009, versjon 2.1 (JSR 338) i 2013, og versjon 2.2 (en vedlikeholdsutgivelse av JSR 338) ble publisert i 2017. JPA 2.2 er valgt for inkludering og pågående utvikling i Jakarta EE.
Komme i gang med JPA
Java Persistence API er en spesifikasjon, ikke en implementering: den definerer en vanlig abstraksjon som du kan bruke i koden din for å samhandle med ORM-produkter. Denne delen gjennomgår noen av de viktige delene av JPA-spesifikasjonen.
Du lærer hvordan du:
- Definer enheter, felt og primærnøkler i databasen.
- Opprett relasjoner mellom enheter i databasen.
- Arbeid med
EntityManager
og dens metoder.
Definere enheter
For å definere en enhet, må du opprette en klasse som er merket med @Enhet
kommentar. De @Enhet
kommentar er en markørkommentar, som brukes til å oppdage vedvarende enheter. Hvis du for eksempel vil opprette en bokenhet, vil du kommentere den som følger:
@Entity public class Book {...}
Som standard vil denne enheten bli kartlagt til Bok
tabellen, som bestemt av det gitte klassenavnet. Hvis du vil tilordne denne enheten til en annen tabell (og eventuelt et bestemt skjema), kan du bruke @Bord
kommentar til å gjøre det. Slik kan du kartlegge Bok
klasse til et BOOKS-bord:
@Entity @Table (name = "BOOKS") offentlig klasse Bok {...}
Hvis BOOKS-tabellen var i PUBLISHING-skjemaet, kan du legge til skjemaet i @Bord
kommentar:
@Table (name = "BOOKS", schema = "PUBLISERING")
Kartlegge felt til kolonner
Når enheten er kartlagt til en tabell, er din neste oppgave å definere feltene. Enger er definert som medlemsvariabler i klassen, og navnet på hvert felt blir kartlagt til et kolonnenavn i tabellen. Du kan overstyre denne standardkartleggingen ved å bruke @Kolonne
kommentar, som vist her:
@Entity @Table (name = "BOOKS") offentlig klasse Bok {privat strengnavn; @Column (name = "ISBN_NUMBER") privat streng isbn; ...}
I dette eksemplet har vi godtatt standardkartleggingen for Navn
attributt, men spesifiserte en tilpasset kartlegging for isbn
Egenskap. De Navn
attributt blir kartlagt til Navn kolonnen, men isbn
attributt blir kartlagt til ISBN_NUMBER-kolonnen.
De @Kolonne
kommentar tillater oss å definere flere egenskaper for feltet / kolonnen, inkludert lengde, om det er null, om det må være unikt, dets presisjon og skala (hvis det er en desimalverdi), om det kan settes inn og oppdateres, og så videre.
Spesifisere hovednøkkelen
Et av kravene til en relasjonell databasetabell er at den må inneholde en primærnøkkel, eller en nøkkel som unikt identifiserer en bestemt rad i databasen. I JPA bruker vi @Id
kommentar for å angi et felt som skal være tabellens primære nøkkel. Primærnøkkelen kreves for å være en primitiv Java-type, en primitiv innpakning, for eksempel Heltall
eller Lang
, a String
, a Dato
, a BigInteger
, eller a BigDecimal
.
I dette eksemplet kartlegger vi id
attributt, som er et Heltall
, til ID-kolonnen i BOOKS-tabellen:
@Entity @Table (name = "BOOKS") offentlig klasse Book {@Id private Integer id; privat strengnavn; @Column (name = "ISBN_NUMBER") privat streng isbn; ...}
Det er også mulig å kombinere @Id
kommentar med @Kolonne
kommentar for å overskrive primærnøkkelens kolonnenavnkartlegging.
Forhold mellom enheter
Nå som du vet hvordan du definerer en enhet, la oss se på hvordan du kan skape relasjoner mellom enheter. JPA definerer fire merknader for å definere enheter:
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
En-til-en-forhold
De @OneToOne
kommentar brukes til å definere en en-til-en-relasjon mellom to enheter. For eksempel kan du ha en Bruker
enhet som inneholder brukerens navn, e-postadresse og passord, men det kan være lurt å opprettholde tilleggsinformasjon om en bruker (for eksempel alder, kjønn og favorittfarge) i en separat Brukerprofil
enhet. De @OneToOne
merknader gjør det lettere å bryte ned data og enheter på denne måten.
De Bruker
klassen nedenfor har en singel Brukerprofil
forekomst. De Brukerprofil
kart til en enkelt Bruker
forekomst.
@Entity public class User {@Id private Integer id; privat streng e-post; privat strengnavn; privat strengpassord; @OneToOne (mappedBy = "bruker") privat brukerprofilprofil; ...}
@Entity public class UserProfile {@Id private Integer id; privat alder; privat String kjønn; privat streng favoritt Farge; @OneToOne privat brukerbruker; ...}
JPA-leverandøren bruker Brukerprofil
s bruker
felt for å kartlegge Brukerprofil
til Bruker
. Kartleggingen er spesifisert i kartlagt av
attributt i @OneToOne
kommentar.
En-til-mange og mange-til-en-forhold
De @OneToMany
og @ManyToOne
merknader letter begge sider av det samme forholdet. Tenk på et eksempel der a Bok
kan bare ha en Forfatter
, men en Forfatter
kan ha mange bøker. De Bok
enhet ville definere en @ManyToOne
forhold med Forfatter
og Forfatter
enhet ville definere en @OneToMany
forhold med Bok
.
@Entity public class Book {@Id private Integer id; privat strengnavn; @ManyToOne @JoinColumn (name = "AUTHOR_ID") privat forfatterforfatter; ...}
@Entity public class Author {@Id @GeneratedValue private Integer id; privat strengnavn; @OneToMany (mappedBy = "forfatter") private Listebøker = ny ArrayList (); ...}
I dette tilfellet Forfatter
klassen fører en liste over alle bøkene som er skrevet av forfatteren og Bok
klasse opprettholder en referanse til sin eneste forfatter. I tillegg har @JoinColumn
angir navnet på kolonnen i Bok
tabell for å lagre IDen til Forfatter
.
Mange-til-mange-forhold
Til slutt, @ManyToMany
kommentar muliggjør et mange-til-mange forhold mellom enheter. Her er et tilfelle der en Bok
enhet har flere Forfatter
s:
@Entity public class Book {@Id private Integer id; privat strengnavn; @ManyToMany @JoinTable (name = "BOOK_AUTHORS", joinColumns = @ JoinColumn (name = "BOOK_ID"), inverseJoinColumns = @ JoinColumn (name = "AUTHOR_ID")) private Sett forfattere = ny HashSet (); ...}
@Entity public class Author {@Id @GeneratedValue private Integer id; privat strengnavn; @ManyToMany (mappedBy = "forfatter") private Sett bøker = nye HashSet (); ...}
I dette eksemplet lager vi en ny tabell, BOOK_AUTHORS
, med to kolonner: BOOK_ID
og AUTHOR_ID
. Bruker bli medKolonner
og inverseJoinColumns
attributter forteller JPA-rammeverket ditt hvordan du kan kartlegge disse klassene i et mange-til-mange forhold. De @ManyToMany
kommentar i Forfatter
klasse refererer til feltet i Bok
klasse som styrer forholdet; nemlig forfattere
eiendom.
Det er en rask demo for et ganske komplekst tema. Vi vil dykke videre inn i @JoinTable
og @JoinColumn
merknader i neste artikkel.
Arbeide med EntityManager
EntityManager
er klassen som utfører databaseinteraksjoner i JPA. Den initialiseres gjennom en konfigurasjonsfil med navnet persistence.xml
. Denne filen finnes i META-INF
mappen i CLASSPATH
, som vanligvis er pakket i JAR- eller WAR-filen. De persistence.xml
filen inneholder:
- Den navngitte "utholdenhetsenheten", som spesifiserer utholdenhetsrammeverket du bruker, for eksempel dvalemodus eller EclipseLink.
- En samling egenskaper som spesifiserer hvordan du kobler til databasen din, samt eventuelle tilpasninger i utholdenhetsrammeverket.
- En liste over enhetsklasser i prosjektet ditt.
La oss se på et eksempel.
Konfigurere EntityManager
Først lager vi en EntityManager
bruker EntityManagerFactory
hentet fra Standhaftighet
klasse:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory ("Bøker"); EntityManager entityManager = entityManagerFactory.createEntityManager ();
I dette tilfellet har vi opprettet en EntityManager
som er koblet til "Books" utholdenhet enhet, som vi har konfigurert i persistence.xml
fil.
De EntityManager
klasse definerer hvordan programvaren vår vil samhandle med databasen gjennom JPA-enheter. Her er noen av metodene som brukes av EntityManager
:
finne
henter en enhet med sin primære nøkkel.createQuery
skaper enSpørsmål
forekomst som kan brukes til å hente enheter fra databasen.createNamedQuery
laster enSpørsmål
som er definert i a@NamedQuery
kommentar inne i en av utholdenhetsenhetene. Navngitte spørsmål gi en ren mekanisme for sentralisering av JPA-spørsmål i definisjonen av utholdenhetsklassen som spørringen skal utføres på.getTransaction
definerer enEntityTransaction
å bruke i databaseinteraksjonene dine. Akkurat som databasetransaksjoner, vil du vanligvis starte transaksjonen, utføre operasjonene dine og deretter enten begå eller tilbakebetale transaksjonen. DegetTransaction ()
metoden lar deg få tilgang til denne oppførselen på nivået medEntityManager
, i stedet for databasen.slå sammen()
legger til en enhet i utholdenhetskonteksten, slik at når transaksjonen blir begått, vil enheten bli videreført til databasen. Når du brukerslå sammen()
, objekter håndteres ikke.fortsette
legger til en enhet i utholdenhetskonteksten, slik at når transaksjonen er begått, vil enheten bli videreført til databasen. Når du brukerfortsette()
, gjenstander administreres.forfriske
oppdaterer tilstanden til gjeldende enhet fra databasen.skyll
synkroniserer tilstanden til utholdenhetskonteksten med databasen.
Ikke bekymre deg for å integrere alle disse metodene samtidig. Du blir kjent med dem ved å jobbe direkte med EntityManager
, som vi vil gjøre mer i neste avsnitt.