¿Qué es JPA? Introducción a la API de persistencia de Java

Como especificación, la API de persistencia de Java se ocupa de la persistencia, que se refiere vagamente a cualquier mecanismo por el cual los objetos Java sobreviven al proceso de aplicación que los creó. No es necesario conservar todos los objetos Java, pero la mayoría de las aplicaciones conservan objetos de negocio clave. La especificación JPA le permite definir qué objetos deben conservarse y cómo deben conservarse en sus aplicaciones Java.

Por sí mismo, JPA no es una herramienta o marco de trabajo; más bien, define un conjunto de conceptos que pueden ser implementados por cualquier herramienta o marco. Si bien el modelo de mapeo objeto-relacional (object) de JPA se basó originalmente en Hibernación, desde entonces ha evolucionado. Del mismo modo, mientras que JPA fue originalmente diseñado para su uso con bases de datos relacionales/SQL, algunas implementaciones de JPA se han ampliado para su uso con almacenes de datos NoSQL. Un framework popular que soporta JPA con NoSQL es EclipseLink, la implementación de referencia para JPA 2.2.

JPA e Hibernación

Debido a su historia entrelazada, Hibernación y JPA se confunden con frecuencia. Sin embargo, al igual que la especificación Java Servlet, JPA ha generado muchas herramientas y frameworks compatibles; Hibernate es solo una de ellas.

Desarrollado por Gavin King y lanzado a principios de 2002, Hibernate es una biblioteca OR para Java. King desarrolló la Hibernación como una alternativa a los frijoles de entidad para la persistencia. El marco era tan popular, y tan necesario en ese momento, que muchas de sus ideas fueron adoptadas y codificadas en la primera especificación de JPA.

Hoy en día, Hibernate OR es una de las implementaciones de JPA más maduras, y sigue siendo una opción popular para Java en Java. Hi de hibernación 5.3.8 (la versión actual en el momento de escribir este artículo) implementa JPA 2.2. Además, la familia de herramientas de Hibernate se ha ampliado para incluir herramientas populares como Hibernate Search, Hibernate Validator y Hibernate OGM, que admite persistencia de modelo de dominio para NoSQL.

¿Qué es Java Java?

Aunque difieren en la ejecución, cada implementación de JPA proporciona algún tipo de capa OR. Para comprender JPA y las herramientas compatibles con JPA, debe tener un buen conocimiento de OR.

La asignación de objetos relacionales es una tarea que los desarrolladores tienen buenas razones para evitar hacer manualmente. Un framework ORM como Hibernate o EclipseLink codifica esa tarea en una biblioteca o framework, una capa ORM. Como parte de la arquitectura de la aplicación, la capa OR es responsable de gestionar la conversión de objetos de software para interactuar con las tablas y columnas de una base de datos relacional. En Java, la capa Java convierte clases y objetos Java para que puedan almacenarse y gestionarse en una base de datos relacional.

De forma predeterminada, el nombre del objeto que se conserva se convierte en el nombre de la tabla y los campos se convierten en columnas. Una vez configurada la tabla, cada fila de la tabla corresponde a un objeto de la aplicación. La asignación de objetos es configurable, pero los valores predeterminados tienden a funcionar bien.

La figura 1 ilustra el papel de JPA y la capa OR en el desarrollo de aplicaciones.

JavaWorld / IDG

Figura 1. JPA y la capa Java

Configurar la capa Java Java

Cuando configure un nuevo proyecto para usar JPA, deberá configurar el almacén de datos y el proveedor de JPA. Configurará un conector de almacén de datos para conectarse a la base de datos elegida (SQL o NoSQL). También incluirás y configurarás el proveedor JPA, que es un framework como Hibernate o EclipseLink. Si bien puede configurar JPA manualmente, muchos desarrolladores optan por usar el soporte listo para usar de Spring. Consulte «Instalación y configuración de JPA» a continuación para obtener una demostración de la instalación y configuración de JPA manual y basada en muelles.

Persistencia de datos en Java

Desde una perspectiva de programación, la capa OR es una capa de adaptador: adapta el lenguaje de los gráficos de objetos al lenguaje de SQL y tablas relacionales. La capa OR permite a los desarrolladores orientados a objetos crear software que conserve datos sin abandonar el paradigma orientado a objetos.

Cuando se utiliza JPA, se crea un mapa desde el almacén de datos a los objetos del modelo de datos de la aplicación. En lugar de definir cómo se guardan y recuperan los objetos, debe definir la asignación entre los objetos y la base de datos y, a continuación, invocar JPA para conservarlos. Si está utilizando una base de datos relacional, gran parte de la conexión real entre el código de su aplicación y la base de datos será manejada por JDBC, la API de Conectividad de base de datos Java.

Como especificación, JPA proporciona anotaciones de metadatos, que se utilizan para definir la asignación entre los objetos y la base de datos. Cada implementación de JPA proporciona su propio motor para anotaciones de JPA. La especificación JPA también proporciona el PersistanceManager o EntityManager, que son los puntos clave de contacto con el sistema JPA (en el que su código de lógica de negocio le dice al sistema qué hacer con los objetos asignados).

Para hacer todo esto más concreto, considere la Lista 1, que es una clase de datos simple para modelar un músico.

Listado 1. Una clase de datos simple en Java

La clase Musician en el listado 1 se utiliza para almacenar datos. Puede contener datos primitivos como el campo de nombre. También puede mantener relaciones con otras clases, tales como mainInstrument y performances.

Musician la razón de ser es contener datos. Este tipo de clase a veces se conoce como DTO o objeto de transferencia de datos. Los TDT son una característica común del desarrollo de software. Si bien contienen muchos tipos de datos, no contienen ninguna lógica de negocio. La persistencia de objetos de datos es un desafío omnipresente en el desarrollo de software.

Persistencia de datos con JDBC

Una forma de guardar una instancia de la clase Musician en una base de datos relacional sería usar la biblioteca JDBC. JDBC es una capa de abstracción que permite que una aplicación emita comandos SQL sin pensar en la implementación de la base de datos subyacente.

El listado 2 muestra cómo se puede mantener la clase Musician utilizando JDBC.

Listado 2. JDBC insertar un registro

El código de la Lista 2 se documenta de forma bastante automática. El objeto georgeHarrison podría venir de cualquier lugar (envío de front-end, servicio externo, etc.), y tiene sus campos ID y nombre establecidos. Los campos del objeto se utilizan para proporcionar los valores de una instrucción SQL insert. (La clase PreparedStatement es parte de JDBC, que ofrece una forma segura de aplicar valores a una consulta SQL.)

Mientras que JDBC permite el control que viene con la configuración manual, es engorroso en comparación con JPA. Para modificar la base de datos, primero debe crear una consulta SQL que se asigne de su objeto Java a las tablas de una base de datos relacional. A continuación, debe modificar el SQL cada vez que cambie una firma de objeto. Con JDBC, mantener el SQL se convierte en una tarea en sí misma.

Persistencia de datos con JPA

Ahora considere Listar 3, donde persistimos la clase Musician usando JPA.

Listado 3. Persistencia de George Harrison con JPA

Musician georgeHarrison = new Musician(0, "George Harrison");musicianManager.save(georgeHarrison);

Listing 3 reemplaza el SQL manual de Listing 2 con una sola línea, session.save(), que indica a JPA que persista el objeto. A partir de entonces, la conversión SQL es manejada por el framework, por lo que nunca tendrá que abandonar el paradigma orientado a objetos.

Anotaciones de metadatos en JPA

La magia de Listing 3 es el resultado de una configuración, que se crea utilizando las anotaciones de JPA. Los desarrolladores usan anotaciones para informar a JPA qué objetos se deben conservar y cómo se deben conservar.

El listado 4 muestra la clase Musician con una sola anotación JPA.

Listado 4. La anotación @Entidad de JPA

@Entitypublic class Musician { // ..class body}

Los objetos persistentes a veces se llaman entidades. Adjuntar @Entity a una clase como Musician informa JPA que esta clase y sus objetos debe ser persistente.

Configurar JPA

Al igual que la mayoría de los frameworks modernos, JPA adopta la codificación por convención (también conocida como convención sobre configuración), en la que el framework proporciona una configuración predeterminada basada en las mejores prácticas de la industria. Por ejemplo, una clase llamada Musician se asignaría de forma predeterminada a una tabla de base de datos llamada Musician.

La configuración convencional es un ahorrador de tiempo, y en muchos casos funciona lo suficientemente bien. También es posible personalizar la configuración de JPA. Como ejemplo, puede usar la anotación @Table de JPA para especificar la tabla donde se debe almacenar la clase Musician.

Listado 5. La anotación @Table de JPA

@Entity@Table(name="musician")public class Musician { // ..class body}

Listing 5 le dice a JPA que mantenga la entidad (Musicianclass) en la tabla musician.

Clave primaria

En JPA, la clave primaria es el campo utilizado para identificar de forma única cada objeto de la base de datos. La clave primaria es útil para hacer referencia y relacionar objetos con otras entidades. Cada vez que almacene un objeto en una tabla, también especificará el campo que utilizará como clave principal.

En el listado 6, le indicamos a JPA qué campo usar como clave primaria de Musician.

Listado 6. Especificar la clave primaria

@Entitypublic class Musician { @Id private Long id;

En este caso, hemos utilizado la anotación @Id de JPA para especificar el campo id como la clave primaria de Musician. De forma predeterminada, esta configuración asume que la clave principal será establecida por la base de datos, por ejemplo, cuando el campo se establece en incremento automático en la tabla.

JPA admite otras estrategias para generar la clave principal de un objeto. También tiene anotaciones para cambiar los nombres de campos individuales. En general, JPA es lo suficientemente flexible como para adaptarse a cualquier asignación de persistencia que pueda necesitar.

Operaciones CRUD

Una vez que haya asignado una clase a una tabla de base de datos y establecido su clave principal, tendrá todo lo que necesita para crear, recuperar, eliminar y actualizar esa clase en la base de datos. Llamar a session.save() creará o actualizará la clase especificada, dependiendo de si el campo de clave primaria es nulo o se aplica a la entidad existente en. Llamar a entityManager.remove() eliminará la clase especificada.

Relaciones de entidades en JPA

Simplemente persistir un objeto con un campo primitivo es solo la mitad de la ecuación. JPA también tiene la capacidad de gestionar entidades en relación entre sí. Cuatro tipos de relaciones de entidad son posibles tanto en tablas como en objetos:

    1. Uno-a-muchos
    2. Muchos-a-uno
    3. Muchos-a-muchos
    4. Uno-a-uno

Cada tipo de relación se describe cómo una entidad se relaciona con otras entidades. Por ejemplo, la etiqueta Musician entidad podría tener una relación de uno a muchos relación con Performance, una entidad representada por una colección como List o Set.

Si el Musician incluye un Band campo, la relación entre estas entidades podrían ser muchos-a-uno, lo que implica la recolección de Musicians en el Band clase. (Suponiendo que cada músico solo actúa en una sola banda.)

SiMusician incluía un campo BandMates, que podría representar una relación de muchos a muchos con otras entidades Musician.

Finalmente, Musician podría tener una relación uno a uno con una entidad Quote, utilizada para representar una cita famosa: Quote famousQuote = new Quote().

Definir tipos de relación

JPA tiene anotaciones para cada uno de sus tipos de asignación de relaciones. Listing 7 muestra cómo puede anotar la relación uno a muchos entre Musician y Performances.

Listing 7. Anotación de una relación de uno a muchos

Una cosa a tener en cuenta es que @JoinColumn le dice a JPA qué columna de la tabla de rendimiento se asignará a la entidad Musician. Cada rendimiento se asociará a un único Musician, que es rastreado por esta columna. Cuando JPA carga un Musician o un Performance en la base de datos, utilizará esta información para reconstituir el gráfico de objetos.

estrategias de Recuperación en JPA

además De saber dónde colocar las entidades relacionadas en la base de datos, JPA necesita saber cómo desea cargar. Las estrategias de obtención le dicen a JPA cómo cargar entidades relacionadas. Al cargar y guardar objetos, un framework JPA debe proporcionar la capacidad de ajustar con precisión cómo se manejan los gráficos de objetos. Por ejemplo, si la clase Musician tiene un campo bandMate (como se muestra en el listado 7), cargar george podría hacer que se cargue toda la tabla Musician desde la base de datos.

Lo que se necesita es la capacidad de definir la carga perezosa de entidades relacionadas, reconociendo, por supuesto, que las relaciones en JPA pueden ser ansiosas o perezosas. Puedes usar anotaciones para personalizar tus estrategias de búsqueda, pero la configuración predeterminada de JPA a menudo funciona de forma inmediata, sin cambios:

  1. Uno a muchos: Perezoso
  2. Muchos a uno: Ansioso
  3. Muchos a muchos: Perezoso
  4. Uno a uno: Ansioso

Instalación y configuración de JPA

Concluiremos con un vistazo rápido a la instalación y configuración de JPA para sus aplicaciones Java. Para esta demostración usaré EclipseLink, la implementación de referencia de JPA.

La forma común de instalar JPA es incluir un proveedor de JPA en el proyecto. El listado 8 muestra cómo incluirías EclipseLink como dependencia en tu archivo Maven pom.xml.

Listado 8. Incluir EclipseLink como una dependencia Maven

org.eclipse.persistenceeclipselink2.5.0-RC1

También deberá incluir el controlador de su base de datos, como se muestra en el Listado 9.

Listado 9. Dependencia Maven para un conector MySQL

mysqlmysql-connector-java5.1.32

A continuación, deberá informar al sistema sobre su base de datos y proveedor. Esto se hace en el archivo persistence.xml, como se muestra en el Listado 10.

Listado 10. Persistencia.xml

Hay otras formas de proporcionar esta información al sistema, incluso mediante programación. Recomiendo usar el archivo persistence.xml porque almacenar dependencias de esta manera hace que sea muy fácil actualizar su aplicación sin modificar el código.

Configuración de resorte para JPA

El uso de resorte facilitará en gran medida la integración de JPA en su aplicación. Por ejemplo, colocar la anotación @SpringBootApplication en el encabezado de la aplicación indica a Spring que busque clases automáticamente e inyecte la anotación EntityManager según sea necesario, en función de la configuración que haya especificado.

El listado 11 muestra las dependencias que se deben incluir si desea el soporte JPA de Spring para su aplicación.

Listado 11. Adición de compatibilidad con Spring JPA en Maven

Conclusión

Cada aplicación que trate con una base de datos debe definir una capa de aplicación cuyo único propósito sea aislar el código de persistencia. Como ha visto en este artículo, la API de persistencia de Java presenta una serie de capacidades y compatibilidad con la persistencia de objetos de Java. Es posible que las aplicaciones simples no requieran todas las capacidades de JPA y, en algunos casos, la sobrecarga de configuración del marco de trabajo no se merezca. Sin embargo, a medida que crece una aplicación, la estructura y encapsulación de JPA realmente se ganan el sustento. El uso de JPA mantiene su código objeto simple y proporciona un marco convencional para acceder a los datos en aplicaciones Java.

Obtenga más información sobre la API de persistencia de Java y las tecnologías relacionadas

  • ¿Qué es JDBC? Introducción a la conectividad de bases de datos Java: Conozca la API de bajo nivel de Java para conectarse a una base de datos, emitir consultas SQL y más.
  • Persistencia de Java con JPA e Hibernación, Parte 1: Entidades y relaciones: Comience a modelar entidades y relaciones con Java 8 e Hibernación OR.
  • Persistencia de Java con JPA e Hibernación, Parte 2: Modelado práctico de relaciones de muchos a muchos y relaciones de herencia en Java 8 y OR de Hibernación.
  • Implementar el comportamiento dependiente de estados: Una introducción clásica al patrón de estado y la dependencia de estados en Java.
  • Carga ansiosa / Perezosa En Hibernación: Cómo aplicar carga ansiosa y perezosa en Hibernación.
  • JPA 2.2 trae algunos cambios muy esperados: Una descripción general de las actualizaciones de especificaciones en JPA 2.2, incluidas mejoras en CDI, una mejor alineación con la API de Fecha y hora y soporte para anotaciones @Repeatable.
  • ¿Debería usar JPA para su próximo proyecto?: Preguntas clave que podrían ayudarte a decidir.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *