Indledning
I denne vejledning vil vi diskutere Hibernate og Java Persistence API (JPA) – med fokus på forskellene mellem dem.
Vi starter med at undersøge, hvad JPA er, hvordan det bruges, og de centrale begreber bag det.
Dernæst ser vi på, hvordan Hibernate og EclipseLink passer ind i billedet.
Object-Relational Mapping
Hvor vi dykker ned i JPA, er det vigtigt at forstå begrebet Object-Relational Mapping – også kendt som ORM.
Objekt-relationel mapping er ganske enkelt processen med at persistere ethvert Java-objekt direkte til en databasetabel. Normalt bliver navnet på det objekt, der persisteres, navnet på tabellen, og hvert felt i dette objekt bliver en kolonne. Når tabellen er oprettet, svarer hver række til en post i programmet.
En introduktion til JPA
Java Persistence API, eller JPA, er en specifikation, der definerer forvaltningen af relationelle data i et Java-program. API’et kortlægger et sæt koncepter, der definerer, hvilke objekter i programmet der skal persisteres, og hvordan de skal persisteres.
Det er vigtigt at bemærke her, at JPA kun er en specifikation, og at det kræver en implementering for at fungere – men mere om det senere.
Nu skal vi diskutere nogle af de centrale JPA-koncepter, som en implementering skal dække.
3.1. Entity
Klassen javax.persistence.Entity definerer, hvilke objekter der skal persisteres til databasen. For hver persisteret entitet opretter JPA en ny tabel i den valgte database.
Dertil kommer, at alle valgte entiteter skal definere en primær nøgle, der angives med annotationen @Id. Sammen med @GeneratedValue-annotationen definerer vi, at den primære nøgle skal genereres automatisk, når posten persisteres til databasen.
Lad os tage et hurtigt eksempel på en entitet beskrevet af JPA.
@Entitypublic class Car { @GeneratedValue @Id public long id; // getters and setters}
Husk, dette vil på nuværende tidspunkt ikke have nogen effekt på applikationen – JPA leverer ingen implementeringskode.
3.2. Field Persistence
Et andet centralt koncept i JPA er field persistence. Når et objekt i Java defineres som en entitet, persisteres alle felter i det automatisk som forskellige kolonner i entitetstabellen.
Hvis der er et felt i et persisteret objekt, som vi ikke ønsker at persistere til databasen, kan vi erklære feltet transient med @Transient-annotationen.
3.3. Relationer
Næst angiver JPA, hvordan vi skal håndtere relationer mellem forskellige databasetabeller i vores applikation. Som vi har set, håndterer JPA dette med annotationer. Der er fire relationsannotationer, som vi skal være opmærksomme på:
- @OneToOne
- @OneToMany
- @ManyToOne
- @ManyToMany
Lad os se på, hvordan dette fungerer:
@Entitypublic class SteeringWheel { @OneToOne private Car car // getters and setters}
I vores eksempel ovenfor beskriver SteeringWheel-klassen et en-til-en-forhold med vores Car-klasse fra tidligere.
3.4. Entity Manager
Endeligt specificerer klassen javax.persistence.EntityManager operationer til og fra databasen. EntityManager indeholder almindelige CRUD-operationer (Create, Read, Update og Delete), der persisteres til databasen.
JPA-implementeringer
Med JPA-specifikationen, der definerer, hvordan og hvad vi skal persistere, skal vi nu vælge en implementeringsudbyder, der leverer den nødvendige kode. Uden en sådan udbyder ville vi skulle implementere alle de relevante klasser for at være i overensstemmelse med JPA, og det er en masse arbejde!
Der er mange udbydere at vælge imellem, og hver af dem har sine egne fordele og ulemper. Når vi skal træffe en beslutning om, hvilken vi skal bruge, bør vi overveje et par af følgende punkter:
- Projektets modenhed – hvor længe har udbyderen eksisteret, og hvor godt dokumenteret er den?
- Underprojekter – har udbyderen nogle nyttige underprojekter til vores nye applikation?
- Community support – er der nogen til at hjælpe os, når vi ender med at få en kritisk fejl?
- Benchmarking – hvor performant er implementeringen?
Selv om vi ikke vil gå i dybden med benchmarking af forskellige JPA-udbydere, indeholder JPA Performance Benchmark (JPAB) værdifuld indsigt i dette.
Med det ud af vejen, lad os tage et kort kig på nogle af de bedste udbydere af JPA.
Hibernate
Hibernate er i sin kerne et objekt-relationelt mapping-værktøj, der leverer en implementering af JPA. Hibernate er en af de mest modne JPA-implementeringer, der findes, med et stort fællesskab, der bakker op om projektet.
Det implementerer alle de javax.persistence-klasser, vi så på tidligere i artiklen, samt tilbyder funktionalitet ud over JPA – Hibernate-værktøjer, validering og søgning. Selv om disse Hibernate-specifikke API’er kan være nyttige, er de ikke nødvendige i applikationer, der kun kræver den grundlæggende JPA-funktionalitet.
Lad os tage et hurtigt kig på, hvad Hibernate tilbyder med @Entity-annotationen.
Selv om den opfylder JPA-kontrakten, tilføjer @org.hibernate.annotations.Entity yderligere metadata, der går ud over JPA-specifikationen. Dette gør det muligt at finjustere persistens af enheder. Lad os f.eks. se på et par annotationer, som Hibernate tilbyder, og som udvider funktionaliteten af @Entity:
- @Table – giver os mulighed for at angive navnet på den tabel, der er oprettet for entiteten
- @BatchSize – angiver batchstørrelsen, når der hentes entiteter fra tabellen
Det er også værd at bemærke et par af de ekstra funktioner, som JPA ikke specificerer, og som kan vise sig nyttige i større applikationer:
- Anpasselige CRUD-statements med annotationerne @SQLInsert, @SQLUpate og @SQLDelete
- Støtte til blød sletning
- Immutable entiteter med annotationen @Immutable
For en dybere dykning i Hibernate og Java persistens – gå over til vores Spring persistens tutorial-serie.
EclipseLink
EclipseLink, der er bygget af Eclipse Foundation, tilbyder en JPA-implementering med åben kildekode. Derudover understøtter EclipseLink en række andre persistensstandarder såsom Java Architecture for XML Binding (JAXB).
Simpelt sagt, i stedet for at persistere et objekt til en række i en database, kortlægger JAXB det til en XML-repræsentation.
Næst ved at sammenligne den samme @Entity-annotationsimplementering ser vi, at EclipseLink igen tilbyder forskellige udvidelser. Mens der ikke er nogen annotation for @BatchSize, som vi så tidligere, tilbyder EclipseLink andre muligheder, som Hibernate ikke har.
For eksempel:
- @ReadOnly – angiver, at den enhed, der skal persisteres, er skrivebeskyttet
- @Struct – definerer klassen til at mappe til en database-“struct”-type
For at læse mere om, hvad EclipseLink har at tilbyde, kan du gå over til vores guide om EclipseLink med Spring.
Konklusion
I denne artikel har vi set på Java Persistence API, eller JPA.
Slutteligt har vi undersøgt, hvordan det adskiller sig fra Hibernate og EclipseLink.