Qual è la differenza tra JPA, Hibernate ed EclipseLink

Quando le persone sono nuove a JPA, Hibernate o EclipseLink, sono spesso confuse sulla differenza tra loro e quale dovrebbero usare nel loro progetto. Se sei uno di loro, non preoccuparti. È molto più facile di quanto sembri.

Diamo prima un’occhiata alle specifiche JPA.

Java Persistence API (JPA)

JPA è un’abbreviazione che sta per Java Persistence API. È una specifica che fa parte di Java EE e definisce un’API per le mappature relazionali degli oggetti e per la gestione di oggetti persistenti. È possibile utilizzare questa API in ambienti Java SE e Java EE.

La specifica è attualmente disponibile nella versione 2.2. È possibile scaricare il documento in https://jcp.org/en/jsr/detail?id=338. Il jar API è disponibile alle seguenti coordinate Maven:

<dependency> <groupId>javax.persistence</groupId> <artifactId>javax.persistence-api</artifactId> <version>2.2</version></dependency>

JPA stesso non fornisce alcuna classe di implementazione. Il jar API contiene solo un set di interfacce che è possibile utilizzare per implementare il livello di persistenza. Ma non puoi usare JPA da solo. È necessario un provider JPA che implementi le specifiche. Ci sono diverse opzioni disponibili. I più popolari sono Hibernate ed EclipseLink. Ma ne parleremo più tardi.

Fino a poco tempo fa, JPA era gestito e sviluppato da un gruppo di esperti seguendo il Java Community Process (JCP). Ciò è cambiato quando Oracle ha annunciato di trasferire tutte le specifiche Java EE alla Eclipse Foundation. Ora siamo nel bel mezzo del processo di transizione, e un nuovo processo di specifica sarà definito a breve.

Cosa è definito dalla specifica JPA

La specifica definisce la maggior parte delle caratteristiche che ho spiegato nei tutorial e video su questo sito. Puoi usarli con tutte le implementazioni JPA conformi.

Diamo un’occhiata ad alcuni dei più importanti.

Bootstrap e mapping di entità di base

Prima di poter iniziare a utilizzare JPA, è necessario aggiungerlo al progetto, configurare un’unità di persistenza, mappare le entità alle tabelle del database e avviarlo. Probabilmente sai già come farlo, e l’ho spiegato in grande dettaglio nel mio articolo Introduttivo con Hibernate.

Quindi, saltiamo questa parte qui e parliamo delle caratteristiche più interessanti.

Associazioni di mappatura

JPA non solo consente di mappare gli attributi di entità semplici alle colonne del database, ma consente anche di mappare le associazioni tra le tabelle del database agli attributi di entità.

@Entitypublic class Review {...@ManyToOneprivate Book book;...}

Questo spesso rende il tuo modello di entità molto comodo da usare perché devi solo chiamare un metodo getter su un’entità per caricare le entità associate. In background, il provider di persistenza esegue tutte le operazioni di database necessarie per recuperare e gestire l’associazione.

Per quanto comodo da usare, questa funzionalità causa spesso problemi di prestazioni. Prima di iniziare a modellare le associazioni tra le tue entità, assicurati di aver compreso l’effetto dei FetchTypes di JPA per evitare problemi di selezione n+1.

JPQL e query native

JPA definisce il proprio linguaggio di query, chiamato JPQL. È simile a SQL ma consente di definire query in base al modello di dominio mappato anziché al modello di tabella del database.

Il seguente frammento di codice mostra una semplice query JPQL. È possibile definire una query ad hoc chiamando il metodo createQuery su EntityManager em. Come puoi vedere, la sintassi sembra molto simile a SQL. Se non hai familiarità con JPQL, dai un’occhiata alla mia Guida JPQL in cui spiego la sua sintassi e le sue capacità in grandi dettagli.

TypedQuery<Book> q = em.createQuery("SELECT b FROM Book b WHERE b.id = :id", Book.class);q.setParameter("id", 1L);Book b = q.getSingleResult();

Quando si esegue tale query, il provider di persistenza interpreta l’istruzione JPQL e genera una query SQL per esso. In questo modo, il provider di persistenza adatta la query al dialetto SQL specifico del database e migliora la portabilità dell’applicazione.

Sfortunatamente, ciò limita anche le funzionalità di query definite dalla specifica o supportate autonomamente dal provider di persistenza. Questo set di funzionalità è significativamente più piccolo di quello offerto da SQL e non include funzionalità di database proprietarie.

Ma ciò non significa che non sia possibile utilizzare query avanzate o complesse con JPA. È progettato come un’astrazione che perde e consente di eseguire query SQL native. Questi non vengono analizzati dal provider di persistenza ed è possibile utilizzare tutte le funzionalità supportate dal database. Ma tieni presente che ciò potrebbe influire negativamente sulla portabilità del tuo database.

L’esecuzione di una query nativa è piuttosto semplice. Devi solo chiamare il metodo createNativeQuery invece del metodo createQuery sul tuo EntityManager con una query SQL nativa.

Query q = em.createNativeQuery("SELECT * FROM book b WHERE id = :id", Book.class);q.setParameter("id", 1L);Book b = (Book) q.getSingleResult();

Tipi di dati personalizzati

La specifica JPA definisce la mappatura per la maggior parte dei tipi standard senza limitarti a loro. Da JPA 2.1, è possibile supportare facilmente tipi di dati personalizzati con un AttributeConverter. Hai solo bisogno di implementare l’interfaccia AttributeConverter e annotare la classe con un’annotazione @Converter.

Ecco un esempio di un convertitore di attributi che definisce una mappatura personalizzata per il mio 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 e Hibernate

Come ho detto prima, hai bisogno di un provider JPA, se vuoi usare le specifiche JPA nel tuo progetto. Implementa le interfacce come definite dalla specifica. I più popolari sono EclipseLink e Hibernate.

Un vantaggio dell’API standardizzata fornita da JPA è che devi solo aggiungere la sua implementazione in fase di runtime e che puoi sostituirla con una diversa senza modificare alcun codice. L’API standardizzata rende EclipseLink e Hibernate intercambiabili.

Quindi, perché hai bisogno di implementazioni diverse?

Le implementazioni JPA sono gestite da team indipendenti e puoi scegliere quello che fornisce le migliori prestazioni o supporto per lo stack di applicazioni e tecnologie. Si differenziano anche fornendo funzionalità aggiuntive e non standard. Questo è spesso usato per guidare l’innovazione. La popolare funzionalità proprietaria di oggi potrebbe essere il primo passo verso la prossima aggiunta allo standard JPA. L’utilizzo di una qualsiasi di queste funzionalità proprietarie, ovviamente, rende molto più difficile sostituire una specifica implementazione JPA.

EclipseLink

EclipseLink è l’implementazione di riferimento di JPA e implementa JPA versione 2.2. È stato uno dei primi progetti che è diventato parte di EE4J.

Il modo più semplice per aggiungere EclipseLink al tuo progetto è usare le seguenti coordinate Maven.

<dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.7.1</version></dependency>

Interessanti funzionalità proprietarie

Oltre alle funzionalità definite dallo standard JPA, EclipseLink offre anche diverse interessanti funzionalità proprietarie, come:

  • Gestione degli eventi di modifica del database
  • Unità di persistenza composita per mappare entità a tabelle in più database
  • Il supporto per la multi-tenancy

Hibernate

Hibernate è l’implementazione molto popolare di Red Hat della specifica JPA. Implementa quasi tutte le funzionalità definite da JPA 2.2 e rilascerà presto una versione completamente conforme.

La seguente dipendenza Maven aggiunge Hibernate al tuo progetto.

<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>5.1.11</version></dependency>

Interessante funzionalità proprietarie

Simile a EclipseLink, Hibernate fornisce un sacco di interessanti funzionalità proprietarie, come:

  • supporto Esteso per naturale Id
  • il Caricamento di più soggetti per la loro chiave primaria
  • Gestione e la creazione e l’aggiornamento timestamp
  • Entrare associata, enti query
  • Supporto per il multi-tenancy

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.