Cuál es la diferencia entre JPA, Hibernación y EclipseLink

Cuando las personas son nuevas en JPA, Hibernación o EclipseLink, a menudo se confunden sobre la diferencia entre ellas y cuál deben usar en su proyecto. Si eres uno de ellos, no te preocupes. Es mucho más fácil de lo que parece.

Primero echemos un vistazo a la especificación de JPA.

Java Persistence API (JPA)

JPA es una abreviatura de Java Persistence API. Es una especificación que forma parte de Java EE y define una API para asignaciones relacionales de objetos y para administrar objetos persistentes. Puede utilizar esta API en entornos Java SE y Java EE.

La especificación está disponible actualmente en la versión 2.2. Puede descargar el documento en: https://jcp.org/en/jsr/detail?id=338. El jar de API está disponible en las siguientes coordenadas Maven:

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

JPA en sí no proporciona ninguna clase de implementación. El jar de API solo contiene un conjunto de interfaces que puede usar para implementar su capa de persistencia. Pero no puedes usar JPA solo. Necesita un proveedor de JPA que implemente la especificación. Hay varias opciones disponibles. Los más populares son Hibernate y EclipseLink. Pero más sobre eso más adelante.

Hasta hace poco, JPA era gestionado y desarrollado por un grupo de expertos siguiendo el Proceso de la Comunidad Java (JCP). Eso cambió cuando Oracle anunció que transferiría todas las especificaciones de Java EE a Eclipse Foundation. Ahora estamos en medio del proceso de transición, y pronto se definirá un nuevo proceso de especificación.

Lo que define la especificación de JPA

La especificación define la mayoría de las características que expliqué en los tutoriales y videos de este sitio. Puede usarlos con todas las implementaciones de JPA compatibles.

echemos un vistazo a algunos de los más importantes.

Bootstrap y asignaciones básicas de entidades

Antes de comenzar a usar JPA, debe agregarlo a su proyecto, configurar una unidad de persistencia, asignar entidades a las tablas de su base de datos y arrancarlo. Probablemente ya sepas cómo hacerlo, y lo expliqué con gran detalle en mi artículo Introducción a la Hibernación.

Entonces, saltemos esta parte aquí y hablemos de las características más interesantes.

Asociaciones de asignación

JPA no solo le permite asignar atributos de entidad simples a columnas de base de datos, sino que también le permite asignar asociaciones entre tablas de base de datos a atributos de entidad.

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

Que a menudo hace que su modelo de entidad sea muy cómodo de usar porque solo necesita llamar a un método getter en una entidad para cargar las entidades asociadas. En segundo plano, el proveedor de persistencia realiza todas las operaciones de base de datos necesarias para recuperar y administrar la asociación.

Por muy cómodo que pueda ser, estas características a menudo causan problemas de rendimiento. Antes de comenzar a modelar asociaciones entre sus entidades, asegúrese de comprender el efecto de los FetchTypes de JPA para evitar problemas de selección n+1.

JPQL y Consultas nativas

JPA define su propio lenguaje de consulta, llamado JPQL. Es similar a SQL, pero le permite definir consultas basadas en el modelo de dominio asignado en lugar del modelo de tabla de la base de datos.

El siguiente fragmento de código muestra una consulta JPQL simple. Puede definir una consulta ad-hoc llamando al método createQuery en el em EntityManager. Como puede ver, la sintaxis es muy similar a SQL. Si no está familiarizado con JPQL, eche un vistazo a mi Guía de JPQL en la que explico su sintaxis y capacidades con grandes detalles.

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

Cuando ejecuta una consulta de este tipo, su proveedor de persistencia interpreta la instrucción JPQL y genera una consulta SQL para ella. Al hacerlo, el proveedor de persistencia adapta la consulta al dialecto SQL específico de la base de datos y mejora la portabilidad de la aplicación.

Desafortunadamente, eso también lo limita a las características de consulta definidas por la especificación o soportadas por su proveedor de persistencia. Este conjunto de características es significativamente más pequeño que el ofrecido por SQL y no incluye ninguna característica de base de datos propietaria.

Pero eso no significa que no pueda usar ninguna consulta avanzada o compleja con JPA. Está diseñado como una abstracción con fugas y le permite ejecutar consultas SQL nativas. Su proveedor de persistencia no los analiza y puede usar todas las funciones compatibles con su base de datos. Pero tenga en cuenta que esto podría afectar negativamente la portabilidad de su base de datos.

Ejecutar una consulta nativa es bastante simple. Solo necesita llamar al método createNativeQuery en lugar del método createQuery en su EntityManager con una consulta SQL nativa.

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

Tipos de Datos Personalizados

La especificación JPA define la asignación para la mayoría de los tipos estándar sin limitación a ellos. Desde JPA 2.1, puede admitir fácilmente tipos de datos personalizados con un convertidor de atributos. Solo necesita implementar la interfaz AttributeConverter y anotar la clase con una anotación @Converter.

Este es un ejemplo de un convertidor de atributos que define una asignación personalizada para mi enumeración de estado de autor.

@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 Hibernación

Como dije antes, necesita un proveedor de JPA, si desea usar la especificación JPA en su proyecto. Implementa las interfaces tal como se definen en la especificación. Los más populares son EclipseLink e Hibernar.

Una ventaja de la API estandarizada proporcionada por JPA es que solo necesita agregar su implementación en tiempo de ejecución y que puede reemplazarla por una diferente sin cambiar ningún código. La API estandarizada hace que el EclipseLink y la Hibernación sean intercambiables.

Entonces, ¿por qué necesita diferentes implementaciones?

Las implementaciones de JPA son administradas por equipos independientes, y puede elegir la que proporcione el mejor rendimiento o soporte para su pila de aplicaciones y tecnología. También se diferencian al proporcionar funcionalidades adicionales no estándar. Esto se utiliza a menudo para impulsar la innovación. La característica patentada popular de hoy en día podría ser el primer paso para la próxima adición al estándar JPA. El uso de cualquiera de estas características propietarias, obviamente, hace que sea mucho más difícil reemplazar una implementación de JPA específica.

EclipseLink

EclipseLink es la implementación de referencia de JPA e implementa la versión 2.2 de JPA. Fue uno de los primeros proyectos que se convirtió en parte de EE4J.

La forma más fácil de agregar EclipseLink a su proyecto es usar las siguientes coordenadas Maven.

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

Características patentadas interesantes

Además de las características definidas por el estándar JPA, EclipseLink también ofrece varias características patentadas interesantes, como:

  • Manejo de eventos de cambio de base de datos
  • Unidades de persistencia compuestas para asignar entidades a tablas en múltiples bases de datos
  • Soporte para múltiples tenencias

Hibernar

Hibernar es la implementación muy popular de Red Hat de la especificación JPA. Implementa casi todas las características definidas por JPA 2.2 y pronto lanzará una versión totalmente compatible.

La siguiente dependencia Maven añade Hibernación a tu proyecto.

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

Características propietarias interesantes

Similar a EclipseLink, Hibernate proporciona un montón de características propietarias interesantes, como:

  • Soporte extendido para identificadores naturales
  • Cargar varias entidades por su clave primaria
  • Gestión de marcas de tiempo de creación y actualización
  • Unirse a entidades no asociadas en consultas
  • Soporte para arrendamiento múltiple

Deja una respuesta

Tu dirección de correo electrónico no será publicada.