wanneer mensen nieuw zijn in JPA, Hibernate of EclipseLink, zijn ze vaak verward over het verschil tussen hen en welke ze moeten gebruiken in hun project. Als je een van hen bent, maak je geen zorgen. Het is een stuk makkelijker dan het lijkt.
laten we eerst de JPA-specificatie bekijken.
Java Persistence API (JPA)
JPA is een afkorting die staat voor Java Persistence API. Het is een specificatie die deel uitmaakt van Java EE en definieert een API voor object-relationele toewijzingen en voor het beheren van persistente objecten. U kunt deze API gebruiken in Java SE en Java EE omgevingen.
de specificatie is momenteel beschikbaar in versie 2.2. U kunt het document downloaden op https://jcp.org/en/jsr/detail?id=338. De API jar is beschikbaar op de volgende Maven coördinaten:
<dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version></dependency>
JPA zelf biedt geen implementatieklassen. De API jar bevat gewoon een set van interfaces die u kunt gebruiken om uw persistentie laag te implementeren. Maar je kunt JPA niet alleen gebruiken. Je hebt een JPA provider nodig die de specificatie implementeert. Er zijn verschillende opties beschikbaar. De meest populaire zijn overwintering en EclipseLink. Maar daarover later meer.
tot voor kort werd PPA beheerd en ontwikkeld door een deskundigengroep volgens het Java Community Process (JCP). Dat veranderde toen Oracle aankondigde alle Java EE-specificaties over te dragen naar de Eclipse Foundation. We zijn nu in het midden van het overgangsproces, en een nieuw specificatieproces zal binnenkort worden gedefinieerd.
Wat is gedefinieerd door de JPA specificatie
de specificatie definieert de meeste functies die ik heb uitgelegd in de tutorials en video ‘ s op deze site. U kunt ze gebruiken met alle compatibele JPA-implementaties.
laten we eens kijken naar enkele van de belangrijkste.
Bootstrapping en basic entity mappings
voordat u JPA kunt gebruiken, moet u het toevoegen aan uw project, een persistence unit configureren, entiteiten toewijzen aan uw database tabellen en bootstrap het. Je weet waarschijnlijk al hoe dat te doen, en ik legde het in groot detail in mijn aan de slag met winterslaap artikel.
dus, laten we dit deel hier overslaan en praten over de meer interessante functies.
toewijzen van associaties
JPA stelt u niet alleen in staat om eenvoudige entiteitattributen toe te wijzen aan Databasekolommen, maar het staat u ook toe om associaties tussen databasetabellen toe te wijzen aan entiteitattributen.
@Entitypublic class Review {...@ManyToOneprivate Book book;...}
dat maakt uw entity model vaak zeer comfortabel om te gebruiken, omdat je gewoon een getter methode op een entiteit moet aanroepen om de geassocieerde entiteiten te laden. Op de achtergrond voert de persistence provider alle vereiste databasebewerkingen uit om de associatie op te halen en te beheren.
zo comfortabel in gebruik als dit zou kunnen zijn, deze functies veroorzaken vaak problemen met de prestaties. Voordat je begint met het modelleren van associaties tussen je entiteiten, zorg er dan voor dat je het effect begrijpt van JPA ‘ s FetchTypes om n+1 Select problemen te voorkomen.
JPQL en Native Queries
JPA definieert zijn eigen query taal, genaamd JPQL. Het is vergelijkbaar met SQL, maar stelt u in staat om query ‘ s te definiëren op basis van het toegewezen domeinmodel in plaats van het tabelmodel van de database.
het volgende codefragment toont een eenvoudige jpql query. U kunt een ad-hoc query definiëren door het aanroepen van de createQuery methode op de EntityManager em. Zoals je kunt zien, lijkt de syntaxis erg op SQL. Als je niet bekend bent met JPQL, neem dan een kijkje op mijn Jpql gids waarin ik de syntaxis en mogelijkheden in grote details uit te leggen.
TypedQuery<Book> q = em.createQuery("SELECT b FROM Book b WHERE b.id = :id", Book.class);q.setParameter("id", 1L);Book b = q.getSingleResult();
wanneer u een dergelijke query uitvoert, interpreteert uw persistence provider het jpql statement en genereert er een SQL query voor. Door dat te doen, de persistence provider past de query aan de database-specifieke SQL dialect en verbetert de draagbaarheid van uw toepassing.
helaas beperkt dat u ook tot de query-functies die zijn gedefinieerd door de specificatie of die worden ondersteund door uw persistence provider. Deze functieset is aanzienlijk kleiner dan die van SQL en bevat geen eigen databasefuncties.
maar dat betekent niet dat u geen geavanceerde of complexe query ‘ s met JPA kunt gebruiken. Het is ontworpen als een lekkende abstractie en kunt u native SQL query ‘ s uit te voeren. Deze worden niet ontleed door uw persistence provider, en u kunt alle functies die door uw database worden ondersteund gebruiken. Maar houd er rekening mee dat dit een negatieve invloed kan hebben op uw database portabiliteit.
het uitvoeren van een native query is vrij eenvoudig. U hoeft alleen maar de createNativeQuery methode te bellen in plaats van de createQuery methode op uw EntityManager met een native SQL query.
Query q = em.createNativeQuery("SELECT * FROM book b WHERE id = :id", Book.class);q.setParameter("id", 1L);Book b = (Book) q.getSingleResult();
aangepaste gegevenstypen
de JPA-specificatie definieert de toewijzing voor de meeste standaardtypen zonder u daartoe te beperken. Sinds JPA 2.1 kunt u eenvoudig aangepaste gegevenstypen ondersteunen met een AttributeConverter. Je hoeft alleen maar de AttributeConverter-interface te implementeren en de klasse te annoteren met een @Converter-annotatie.
Hier is een voorbeeld van een attribuut converter die een aangepaste toewijzing definieert voor mijn AuthorStatus 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 and Hibernate
zoals ik al eerder zei, Heb je een JPA provider nodig, als je de JPA specificatie in je project wilt gebruiken. Het implementeert de interfaces zoals gedefinieerd door de specificatie. De meest populaire zijn EclipseLink en overwinteren.
een voordeel van de gestandaardiseerde API die door JPA wordt geleverd, is dat je alleen de implementatie ervan tijdens runtime moet toevoegen en dat je het kunt vervangen door een andere zonder enige code te veranderen. De gestandaardiseerde API maakt EclipseLink en Hibernate uitwisselbaar.
dus, waarom heb je verschillende implementaties nodig?
de JPA-implementaties worden beheerd door onafhankelijke teams, en u kunt degene kiezen die de beste prestaties of ondersteuning biedt voor uw applicatie-en technologiestack. Ze onderscheiden zich ook door extra, niet-standaard functionaliteiten te bieden. Dit wordt vaak gebruikt om innovatie te stimuleren. De populaire, propriëtaire functie van vandaag zou de eerste stap kunnen zijn naar de volgende toevoeging aan de JPA-standaard. Het gebruik van een van deze propriëtaire functies maakt het uiteraard een stuk moeilijker om een specifieke JPA-implementatie te vervangen.
EclipseLink
EclipseLink is JPA ‘ s referentie implementatie en implementeert JPA versie 2.2. Het was een van de eerste projecten die onderdeel werd van EE4J.
De makkelijkste manier om EclipseLink aan je project toe te voegen is door de volgende Maven coördinaten te gebruiken.
<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.7.1</version></dependency>
interessante proprietary features
naast de door de JPA-standaard gedefinieerde features biedt EclipseLink ook een aantal interessante proprietary features, zoals:
- afhandeling van databaseveranderingsgebeurtenissen
- Composite persistence units om entiteiten toe te wijzen aan tabellen in meerdere databases
- ondersteuning voor multi-tenancy
Hibernate
Hibernate is Red Hat ‘ s zeer populaire implementatie van de JPA-specificatie. Het implementeert bijna alle functies gedefinieerd door JPA 2.2 en zal binnenkort een volledig compatibele versie vrijgeven.
de volgende Maven-afhankelijkheid voegt Hibernate toe aan uw project.
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.1.11</version></dependency>
Interessante gepatenteerde functies
Vergelijkbaar met EclipseLink, Hibernate biedt een hoop interessante, eigen kenmerken, zoals:
- Uitgebreide ondersteuning voor de natuurlijke-Id ‘s
- Laden van meerdere entiteiten door hun primaire sleutel
- Management van creatie en update tijdstempels
- Toetreding tot uitzetting entiteiten in query’ s
- Ondersteuning voor multi-tenancy