når folk er nye til JPA, Hibernate eller EclipseLink, er de ofte forvirrede over forskellen mellem dem og hvilken de skal bruge i deres projekt. Hvis du er en af dem, skal du ikke bekymre dig. Det er meget lettere, end det ser ud til.
lad os først se på JPA-specifikationen.
Java Persistens API (JPA)
JPA er en forkortelse, der står for Java Persistens API. Det er en specifikation, der er en del af Java EE og definerer en API til objekt-relationelle tilknytninger og til styring af vedvarende objekter. Du kan bruge denne API i Java SE og Java EE miljøer.
specifikationen er i øjeblikket tilgængelig i version 2.2. Du kan hente dokumentet på https://jcp.org/en/jsr/detail?id=338. API-krukken er tilgængelig på følgende Maven-koordinater:
<dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version></dependency>
JPA selv giver ingen implementeringsklasser. API jar indeholder bare et sæt grænseflader, som du kan bruge til at implementere dit persistenslag. Men du kan ikke bruge JPA alene. Du har brug for en JPA-udbyder, der implementerer specifikationen. Der er flere muligheder. De mest populære er Hibernate og EclipseLink. Men mere om det senere.
indtil for nylig blev JPA administreret og udviklet af en ekspertgruppe efter Java Community Process (JCP). Det ændrede sig, da Oracle annoncerede at overføre alle Java EE-SPECIFIKATIONER til Eclipse Foundation. Vi er nu midt i overgangsprocessen, og en ny specifikationsproces vil snart blive defineret.
hvad er defineret af JPA-specifikationen
specifikationen definerer de fleste af de funktioner, som jeg forklarede i tutorials og videoer på denne side. Du kan bruge dem med alle kompatible JPA-implementeringer.
lad os se på nogle af de vigtigste.
Bootstrapping og grundlæggende enhedskortlægninger
før du kan begynde at bruge JPA, skal du føje det til dit projekt, konfigurere en persistensenhed, kortlægge enheder til dine databasetabeller og bootstrap det. Du ved sikkert allerede, hvordan du gør det, og jeg forklarede det i detaljer i min Kom godt i gang med Hibernate artikel.
så lad os springe over denne del her og tale om de mere interessante funktioner.
Kortlægningsforeninger
JPA giver dig ikke kun mulighed for at kortlægge enkle enhedsattributter til databasekolonner, men det giver dig også mulighed for at kortlægge tilknytninger mellem databasetabeller til enhedsattributter.
@Entitypublic class Review {...@ManyToOneprivate Book book;...}
det gør ofte din enhedsmodel meget behagelig at bruge, fordi du bare skal ringe til en getter-metode på en enhed for at indlæse de tilknyttede enheder. I baggrunden udfører persistensudbyderen alle de krævede databasehandlinger for at hente og administrere tilknytningen.
så behagelig at bruge som dette kan være, forårsager disse funktioner ofte ydelsesproblemer. Før du begynder at modellere foreninger mellem dine enheder, skal du sørge for at forstå effekten af JPA ‘ s FetchTypes for at undgå N+1 select-problemer.
Native forespørgsler
JPA definerer sit eget forespørgselssprog, kaldet JPKL. Du kan definere forespørgsler baseret på den kortlagte domænemodel i stedet for databasens tabelmodel.
følgende kodestykke viser en simpel JPKL-forespørgsel. Du kan definere en ad hoc-forespørgsel ved at kalde metoden Opret forespørgsel på EntityManager em. Som du kan se, ser syntaksen meget ud. Hvis du ikke er bekendt med
TypedQuery<Book> q = em.createQuery("SELECT b FROM Book b WHERE b.id = :id", Book.class);q.setParameter("id", 1L);Book b = q.getSingleResult();
Når du udfører en sådan forespørgsel, fortolker din persistensudbyder sætningen og genererer en forespørgsel til den. Ved at gøre det tilpasser persistensudbyderen forespørgslen til den databasespecifikke dialekt og forbedrer portabiliteten af din applikation.
desværre begrænser det dig også til forespørgselsfunktionerne defineret af specifikationen eller proprietært understøttet af din persistensudbyder. Dette funktionssæt er betydeligt mindre end det, der tilbydes af
men det betyder ikke, at du ikke kan bruge avancerede eller komplekse forespørgsler med JPA. Det er designet som en utæt abstraktion og giver dig mulighed for at udføre indfødte forespørgsler. Disse analyseres ikke af din persistensudbyder, og du kan bruge alle funktioner, der understøttes af din database. Men vær opmærksom på, at dette kan påvirke din databaseportabilitet negativt.
udførelse af en oprindelig forespørgsel er ret enkel. Du skal bare ringe til createnativ-forespørgselsmetoden i stedet for createnativ-forespørgselsmetoden på din EntityManager med en indbygget forespørgsel.
Query q = em.createNativeQuery("SELECT * FROM book b WHERE id = :id", Book.class);q.setParameter("id", 1L);Book b = (Book) q.getSingleResult();
brugerdefinerede datatyper
JPA-specifikationen definerer kortlægningen for de fleste standardtyper uden at begrænse dig til dem. Siden JPA 2.1 kan du nemt understøtte brugerdefinerede datatyper med en AttributeConverter. Du skal bare implementere AttributeConverter-grænsefladen og kommentere klassen med en @Converter-kommentar.
Her er et eksempel på en attributkonverter, der definerer en brugerdefineret kortlægning til min Forfatterstatus enum.
@Converter(autoApply = true)public class AuthorStatusConverter implements AttributeConverter<AuthorStatus, String> {Logger log = Logger.getLogger(AuthorStatusConverter.class.getSimpleName());@Overridepublic String convertToDatabaseColumn(AuthorStatus status) {switch (status) {case NOT_PUBLISHED:logDbConversion(status, "N");return "N";case PUBLISHED:logDbConversion(status, "P");return "P";case SELF_PUBLISHED:logDbConversion(status, "S");return "S";default:throw new IllegalArgumentException("AuthorStatus not supported.");}}@Overridepublic AuthorStatus convertToEntityAttribute(String dbData) {switch (dbData) {case "N":logEntityConversion(AuthorStatus.NOT_PUBLISHED, "N");return AuthorStatus.NOT_PUBLISHED;case "P":logEntityConversion(AuthorStatus.PUBLISHED, "P");return AuthorStatus.PUBLISHED;case "S":logEntityConversion(AuthorStatus.SELF_PUBLISHED, "S");return AuthorStatus.SELF_PUBLISHED;default:throw new IllegalArgumentException("AuthorStatus not supported.");}}private void logDbConversion(AuthorStatus status, String dbData) {log.debug("Convert AuthorStatus enum to .");}private void logEntityConversion(AuthorStatus status, String dbData) {log.debug("Convert DB value to AuthorStatus enum .");}}
EclipseLink og Hibernate
som jeg sagde før, har du brug for en JPA-udbyder, hvis du vil bruge JPA-specifikationen i dit projekt. Det implementerer grænsefladerne som defineret i specifikationen. De mest populære er EclipseLink og dvaletilstand.
en fordel ved den standardiserede API, der leveres af JPA, er, at du bare skal tilføje dens implementering ved kørsel, og at du kan erstatte den med en anden uden at ændre nogen kode. Den standardiserede API gør EclipseLink og Hibernate udskiftelige.
så hvorfor har du brug for forskellige implementeringer?
JPA-implementeringerne administreres af uafhængige teams, og du kan vælge den, der giver den bedste ydelse eller support til din applikations-og teknologistak. De differentierer sig også ved at levere yderligere, ikke-standardiserede funktionaliteter. Dette bruges ofte til at drive innovation. Dagens populære, proprietære funktion kan være det første skridt til den næste tilføjelse til JPA-standarden. Brug af nogen af disse proprietære funktioner gør det naturligvis meget sværere at erstatte en bestemt JPA-implementering.
EclipseLink
EclipseLink er JPA ‘ s referenceimplementering og implementerer JPA version 2.2. Det var et af de første projekter, der blev en del af EE4J.
den nemmeste måde at tilføje EclipseLink til dit projekt er at bruge følgende Maven-koordinater.
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.7.1</version></dependency>
interessante proprietære funktioner
ud over de funktioner, der er defineret af JPA-standarden, tilbyder EclipseLink også flere interessante, proprietære funktioner, som:
- håndtering af databaseændringshændelser
- sammensatte persistensenheder til at kortlægge enheder til tabeller i flere databaser
- Support til multi-tenancy
Hibernate
Hibernate er Red Hats meget populære implementering af JPA-specifikationen. Det implementerer næsten alle funktioner defineret af JPA 2.2 og frigiver snart en fuldt kompatibel version.
følgende Maven afhængighed tilføjer dvale til dit projekt.
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.1.11</version></dependency>
interessante proprietære funktioner
I lighed med EclipseLink giver Hibernate en masse interessante, proprietære funktioner, som:
- udvidet support til naturlige id ‘ er
- indlæser flere enheder efter deres primære nøgle
- styring af oprettelse og opdatering af tidsstempler
- sammenføjning af ikke-tilknyttede enheder i forespørgsler
- støtte til multi-tenancy