Programmering

Java-vedholdenhed med JPA og dvale, del 1: enheder og relationer

Java Persistence API (JPA) er en Java-specifikation, der bygger bro mellem relationelle databaser og objektorienteret programmering. Denne tutorial i to dele introducerer JPA og forklarer, hvordan Java-objekter modelleres som JPA-enheder, hvordan enhedsforhold defineres, og hvordan JPA'er bruges EntityManager med arkivet mønster i dine Java-applikationer.

Bemærk, at denne vejledning bruger dvale som JPA-udbyder. De fleste begreber kan udvides til andre Java-persistensrammer.

Hvad er JPA?

Se "Hvad er JPA? Introduktion til Java Persistence API" for at lære om udviklingen af ​​JPA og relaterede rammer, herunder EJB 3.0. og JDBC.

Objektrelationer i JPA

Relationsdatabaser har eksisteret som et middel til lagring af programdata siden 1970'erne. Mens udviklere i dag har mange alternativer til relationsdatabasen, er denne type database skalerbar og forstået og bruges stadig i vid udstrækning i små og store softwareudviklinger.

Java-objekter i en relationel databasekontekst er defineret som enheder. Enheder placeres i tabeller, hvor de optager kolonner og rækker. Programmører bruger udenlandske nøgler og deltage i tabeller at definere forholdet mellem enheder - nemlig en-til-en, en-til-mange og mange-til-mange relationer. Vi kan også bruge SQL (Structured Query Language) til at hente og interagere med data i individuelle tabeller og på tværs af flere tabeller ved hjælp af udenlandske nøglebegrænsninger. Relationsmodellen er flad, men udviklere kan skrive forespørgsler for at hente data og konstruere objekter fra disse data.

Objekt-relationer impedans uoverensstemmelse

Du er måske bekendt med udtrykket objekt-relationer impedans uoverensstemmelse, der henviser til udfordringen ved at kortlægge dataobjekter til en relationsdatabase. Denne uoverensstemmelse opstår, fordi objektorienteret design ikke er begrænset til en-til-en, en-til-mange og mange-til-mange relationer. I stedet for i objektorienteret design tænker vi på objekter, deres attributter og adfærd, og hvordan objekter forholder sig. To eksempler er indkapsling og arv:

  • Hvis et objekt indeholder et andet objekt, definerer vi dette igennem indkapsling--en har en forhold.
  • Hvis et objekt er en specialisering af et andet objekt, definerer vi dette igennem arv- en er en forhold.

Associering, sammenlægning, komposition, abstraktion, generalisering, realisering og afhængigheder er alle objektorienterede programmeringskoncepter, der kan være udfordrende at kortlægge til en relationel model.

ORM: Objektrelationel kortlægning

Misforholdet mellem objektorienteret design og relationel databasemodellering har ført til en klasse værktøjer, der er udviklet specielt til objektrelationskortlægning (ORM). ORM-værktøjer som dvale, EclipseLink og iBatis oversætter relationelle databasemodeller, inklusive enheder og deres forhold, til objektorienterede modeller. Mange af disse værktøjer eksisterede før JPA-specifikationen, men uden en standard var deres funktioner leverandørafhængige.

Java Persistence API (JPA) blev først frigivet som en del af EJB 3.0 i 2006 og tilbyder en standard måde at kommentere objekter på, så de kan kortlægges og lagres i en relationsdatabase. Specifikationen definerer også en fælles konstruktion til interaktion med databaser. At have en ORM-standard til Java giver konsistens til leverandørimplementeringer, samtidig med at det giver mulighed for fleksibilitet og tilføjelser. Selvom den originale JPA-specifikation finder anvendelse på relationelle databaser, har nogle leverandørimplementeringer udvidet JPA til brug sammen med NoSQL-databaser.

Udvikling af JPA

Den første udgivelse af JPA, version 1.0, blev offentliggjort i 2006 gennem Java Community Process (JCP) som Java Specification Request (JSR) 220. Version 2.0 (JSR 317) blev offentliggjort i 2009, version 2.1 (JSR 338) i 2013, og version 2.2 (en vedligeholdelsesudgivelse af JSR 338) blev offentliggjort i 2017. JPA 2.2 er valgt til inkludering og løbende udvikling i Jakarta EE.

Kom godt i gang med JPA

Java Persistence API er en specifikation og ikke en implementering: den definerer en almindelig abstraktion, som du kan bruge i din kode til at interagere med ORM-produkter. Dette afsnit gennemgår nogle af de vigtige dele af JPA-specifikationen.

Du lærer at:

  • Definer enheder, felter og primære nøgler i databasen.
  • Opret relationer mellem enheder i databasen.
  • Arbejd med EntityManager og dens metoder.

Definere enheder

For at definere en enhed skal du oprette en klasse, der er kommenteret med @Enhed kommentar. Det @Enhed kommentar er en markørnotering, som bruges til at opdage vedvarende enheder. Hvis du f.eks. Vil oprette en bogenhed, vil du kommentere den som følger:

 @Entity public class Book {...} 

Som standard kortlægges denne enhed til Bestil tabel, som bestemt af det givne klassenavn. Hvis du vil kortlægge denne enhed til en anden tabel (og eventuelt et bestemt skema), kan du bruge @Bord kommentar til at gøre det. Sådan kan du kortlægge Bestil klasse til et BOOKS-bord:

 @Entity @Table (name = "BOOKS") offentlig klasse Bog {...} 

Hvis BOOKS-tabellen var i PUBLISHING-skemaet, kan du føje skemaet til @Bord kommentar:

 @Table (name = "BOOKS", skema = "PUBLICERING") 

Kortlægning af felter til kolonner

Med enheden tilknyttet en tabel, er din næste opgave at definere dens felter. Felter er defineret som medlemsvariabler i klassen, hvor navnet på hvert felt kortlægges til et kolonnenavn i tabellen. Du kan tilsidesætte denne standardkortlægning ved hjælp af @Kolonne kommentar, som vist her:

 @Entity @Table (name = "BOOKS") offentlig klasse Bog {privat strengnavn; @Column (name = "ISBN_NUMBER") privat streng isbn; ...} 

I dette eksempel har vi accepteret standardkortlægningen til navn attribut men specificerede en brugerdefineret kortlægning for isbn attribut. Det navn attribut vil blive kortlagt til navn kolonne, men isbn attribut bliver kortlagt til kolonnen ISBN_NUMBER.

Det @Kolonne kommentar giver os mulighed for at definere yderligere egenskaber for feltet / kolonnen, inklusive længde, om det er ugyldigt, om det skal være unikt, dets præcision og skala (hvis det er en decimalværdi), om det kan indsættes og opdateres osv.

Angivelse af den primære nøgle

Et af kravene til en relationsdatabasetabel er, at den skal indeholde en primærnøgle, eller en nøgle, der entydigt identificerer en bestemt række i databasen. I JPA bruger vi @Id kommentar for at angive et felt, der skal være tabellens primære nøgle. Den primære nøgle kræves for at være en Java primitiv type, en primitiv indpakning, såsom Heltal eller Lang, a Snor, a Dato, a BigInteger, eller a BigDecimal.

I dette eksempel kortlægger vi id attribut, som er en Heltaltil ID-kolonnen i BOOKS-tabellen:

 @Entity @Table (name = "BOOKS") offentlig klasse Bog {@Id privat heltal id; privat strengnavn; @Column (name = "ISBN_NUMBER") privat streng isbn; ...} 

Det er også muligt at kombinere @Id kommentar med @Kolonne kommentar for at overskrive den primære nøgles kortlægning af kolonnenavn.

Forhold mellem enheder

Nu hvor du ved, hvordan du definerer en enhed, skal vi se på, hvordan man opretter relationer mellem enheder. JPA definerer fire annoteringer for at definere enheder:

  • @En til en
  • @OneToMany
  • @ManyToOne
  • @ManyToMany

En-til-en-forhold

Det @En til en annotering bruges til at definere en en-til-en-relation mellem to enheder. For eksempel kan du have en Bruger enhed, der indeholder en brugers navn, e-mailadresse og adgangskode, men du vil muligvis bevare yderligere oplysninger om en bruger (såsom alder, køn og favoritfarve) i en separat Brugerprofil enhed. Det @En til en annotering letter nedbrydning af dine data og enheder på denne måde.

Det Bruger klasse nedenfor har en enkelt Brugerprofil eksempel. Det Brugerprofil kort til en enkelt Bruger eksempel.

 @Entity offentlig klasse bruger {@Id privat heltal id; privat streng-mail; privat strengnavn; privat strengadgangskode; @OneToOne (mappedBy = "bruger") privat UserProfile-profil; ...} 
 @Entity offentlig klasse UserProfile {@Id privat heltal-id; privat int alder privat String køn; private streng favoritFarve; @OneToOne privat brugerbruger; ...} 

JPA-udbyderen bruger Brugerprofil's bruger felt til kort Brugerprofil til Bruger. Kortlægningen er specificeret i kortlagt af attribut i @En til en kommentar.

En-til-mange og mange-til-en relationer

Det @OneToMany og @ManyToOne annoteringer letter begge sider af det samme forhold. Overvej et eksempel, hvor en Bestil kan kun have en Forfatter, men en Forfatter kan have mange bøger. Det Bestil enhed ville definere en @ManyToOne forhold til Forfatter og Forfatter enhed ville definere en @OneToMany forhold til Bestil.

 @Entity public class Book {@Id privat heltal-id; privat strengnavn; @ManyToOne @JoinColumn (name = "AUTHOR_ID") privat forfatterforfatter; ...} 
 @Entity public class Forfatter {@Id @GeneratedValue privat heltal-id; privat strengnavn; @OneToMany (mappedBy = "author") private Listebøger = ny ArrayList (); ...} 

I dette tilfælde er Forfatter klasse opretholder en liste over alle bøger skrevet af forfatteren og Bestil klasse opretholder en henvisning til sin eneste forfatter. Derudover er @JoinColumn angiver kolonnens navn i Bestil tabel til at gemme id'et på Forfatter.

Mange-til-mange relationer

Endelig blev @ManyToMany annotering letter et mange-til-mange forhold mellem enheder. Her er et tilfælde, hvor en Bestil enhed har flere Forfatters:

 @Entity public class Book {@Id privat heltal-id; privat strengnavn; @ManyToMany @JoinTable (name = "BOOK_AUTHORS", joinColumns = @ JoinColumn (name = "BOOK_ID"), inverseJoinColumns = @ JoinColumn (name = "AUTHOR_ID")) private sæt forfattere = nyt HashSet (); ...} 
 @Entity public class Forfatter {@Id @GeneratedValue privat heltal id; privat strengnavn; @ManyToMany (mappedBy = "author") private Sæt bøger = nyt HashSet (); ...} 

I dette eksempel opretter vi en ny tabel, BOOK_AUTHORSmed to kolonner: BOOK_ID og AUTHOR_ID. Bruger joinColumns og inverseJoinColumns attributter fortæller din JPA-ramme, hvordan man kortlægger disse klasser i et mange-til-mange forhold. Det @ManyToMany kommentar i Forfatter klasse henviser til feltet i Bestil klasse, der styrer forholdet; nemlig forfattere ejendom.

Det er en hurtig demo for et ret komplekst emne. Vi dykker længere ned i @JoinTable og @JoinColumn kommentarer i den næste artikel.

Arbejde med EntityManager

EntityManager er den klasse, der udfører databaseinteraktioner i JPA. Det initialiseres via en konfigurationsfil med navnet persistence.xml. Denne fil findes i META-INF mappe i din CLASSPATH, som typisk er pakket i din JAR- eller WAR-fil. Det persistence.xml filen indeholder:

  • Den navngivne "vedholdenhedsenhed", der specificerer den vedvarende ramme, du bruger, såsom Hibernate eller EclipseLink.
  • En samling af egenskaber, der specificerer, hvordan du opretter forbindelse til din database, samt eventuelle tilpasninger i persistens-rammen.
  • En liste over enhedsklasser i dit projekt.

Lad os se på et eksempel.

Konfiguration af EntityManager

Først opretter vi en EntityManager bruger EntityManagerFactory hentet fra Udholdenhed klasse:

 EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory ("Bøger"); EntityManager entityManager = entityManagerFactory.createEntityManager (); 

I dette tilfælde har vi oprettet en EntityManager der er forbundet til "Bøger" vedholdenhed enhed, som vi har konfigureret i persistence.xml fil.

Det EntityManager klasse definerer, hvordan vores software vil interagere med databasen gennem JPA-enheder. Her er nogle af de metoder, der bruges af EntityManager:

  • finde henter en enhed med dens primære nøgle.
  • createQuery skaber en Forespørgsel forekomst, der kan bruges til at hente enheder fra databasen.
  • createNamedQuery belastninger a Forespørgsel der er defineret i en @NamedQuery kommentar inde i en af ​​de vedholdende enheder. Navngivne forespørgsler give en ren mekanisme til centralisering af JPA-forespørgsler i definitionen af ​​den persistensklasse, som forespørgslen udføres på.
  • getTransaction definerer en EntityTransaction at bruge i dine databaseinteraktioner. Ligesom databasetransaktioner starter du typisk transaktionen, udfører dine operationer og derefter enten begår eller tilbagefører din transaktion. Det getTransaction () metoden giver dig adgang til denne adfærd på niveauet for EntityManager, snarere end databasen.
  • fusionere() tilføjer en enhed til persistens-konteksten, så når transaktionen begås, forbliver enheden i databasen. Ved brug fusionere(), genstande administreres ikke.
  • vedvarer tilføjer en enhed til persistens-konteksten, så når transaktionen begås, forbliver enheden i databasen. Ved brug vedvarer (), objekter administreres.
  • Opdater opdaterer tilstanden for den aktuelle enhed fra databasen.
  • Flush synkroniserer tilstanden af ​​persistens-konteksten med databasen.

Du skal ikke bekymre dig om at integrere alle disse metoder på én gang. Du lærer dem at kende ved at arbejde direkte med EntityManager, som vi gør mere i næste afsnit.

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