Introducción a Spring Data JPA

1. Información general

Este artículo se centrará en introducir Spring Data JPA en un proyecto de Spring y configurar completamente la capa de persistencia. Para obtener una introducción paso a paso sobre cómo configurar el contexto de Spring usando la configuración basada en Java y el pom básico de Maven para el proyecto, consulte este artículo.

2. DAO generado por Spring Data: no más implementaciones de DAO

Como discutimos en un artículo anterior, la capa DAO generalmente consta de una gran cantidad de código repetitivo que puede y debe simplificarse. Las ventajas de tal simplificación son muchas: una disminución en la cantidad de artefactos que necesitamos definir y mantener, consistencia de patrones de acceso a datos y consistencia de configuración.

Spring Data lleva esta simplificación un paso adelante y hace posible eliminar las implementaciones de DAO por completo . La interfaz del DAO es ahora el único artefacto que necesitamos definir explícitamente.

Para comenzar a aprovechar el modelo de programación Spring Data con JPA, una interfaz DAO necesita extender la interfaz de repositorio específica de JPA : JpaRepository . Esto permitirá que Spring Data encuentre esta interfaz y cree automáticamente una implementación para ella.

Al extender la interfaz, obtenemos los métodos CRUD más relevantes para el acceso a datos estándar disponibles en un DAO estándar.

3. Consultas y método de acceso personalizado

Como se discutió, al implementar una de las interfaces del repositorio , el DAO ya tendrá algunos métodos (y consultas) CRUD básicos definidos e implementados .

Para definir métodos de acceso más específicos, Spring JPA admite bastantes opciones:

  • simplemente defina un nuevo método en la interfaz
  • proporcione la consulta JPQL real utilizando la anotación @Query
  • use el soporte más avanzado de especificación y consulta en Spring Data
  • definir consultas personalizadas a través de consultas con nombre JPA

La tercera opción, la compatibilidad con especificaciones y consultas, es similar a los criterios JPA pero utiliza una API más flexible y conveniente. Esto hace que toda la operación sea mucho más legible y reutilizable. Las ventajas de esta API serán más pronunciadas cuando se trate de una gran cantidad de consultas fijas, ya que potencialmente podríamos expresarlas de manera más concisa a través de una menor cantidad de bloques reutilizables.

Esta última opción tiene la desventaja de que involucra XML o sobrecarga la clase de dominio con las consultas.

3.1. Consultas personalizadas automáticas

Cuando Spring Data crea una nueva implementación de Repositorio , analiza todos los métodos definidos por las interfaces e intenta generar automáticamente consultas a partir de los nombres de los métodos . Si bien esto tiene algunas limitaciones, es una forma muy poderosa y elegante de definir nuevos métodos de acceso personalizados con muy poco esfuerzo.

Veamos un ejemplo: si la entidad tiene un campo de nombre (y los métodos getName y setName estándar de Java Bean ), definiremos el método findByName en la interfaz DAO ; esto generará automáticamente la consulta correcta:

public interface IFooDAO extends JpaRepository { Foo findByName(String name); }

Este es un ejemplo relativamente simple. El mecanismo de creación de consultas admite un conjunto mucho mayor de palabras clave.

En caso de que el analizador no pueda hacer coincidir la propiedad con el campo del objeto de dominio, veremos la siguiente excepción:

java.lang.IllegalArgumentException: No property nam found for type class com.baeldung.spring.data.persistence.model.Foo

3.2. Consultas personalizadas manuales

Veamos ahora una consulta personalizada que definiremos a través de la anotación @Query :

@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)") Foo retrieveByName(@Param("name") String name);

Para un control aún más detallado sobre la creación de consultas, como el uso de parámetros con nombre o la modificación de consultas existentes, la referencia es un buen lugar para comenzar.

4. Configuración de transacciones

La implementación real del DAO administrado por Spring está de hecho oculta, ya que no trabajamos con él directamente. Sin embargo, esta es una aplicación bastante simple - el SimpleJpaRepository - que define la semántica de transacción utilizando anotaciones .

Más explícitamente, esto usa una anotación @Transactional de solo lectura en el nivel de clase, que luego se anula para los métodos que no son de solo lectura. El resto de la semántica de la transacción es predeterminada, pero se puede anular fácilmente manualmente por método.

4.1. La traducción de la excepción está viva y bien

La pregunta es ahora, dado que Spring Data JPA no depende de las viejas plantillas ORM ( JpaTemplate , HibernateTemplate ) y se han eliminado desde Spring 5, ¿seguiremos traduciendo nuestras excepciones JPA a la jerarquía de Spring DataAccessException ?

Por supuesto, lo estamos: la traducción de excepciones aún está habilitada mediante el uso de la anotación @Repository en el DAO . Esta anotación permite que un postprocesador de frijoles de Spring avise a todos los frijoles de @Repository con todas las instancias de PersistenceExceptionTranslator encontradas en el contenedor y proporcione la traducción de excepciones como antes.

Verifiquemos la traducción de excepciones con una prueba de integración:

@Test(expected = DataIntegrityViolationException.class) public void givenFooHasNoName_whenInvalidEntityIsCreated_thenDataException() { service.create(new Foo()); }

Tenga en cuenta que la traducción de excepciones se realiza a través de proxies. Para que Spring pueda crear proxies alrededor de las clases DAO, estos no deben declararse definitivos .

5. Configuración del repositorio Spring Data JPA

Para activar el soporte del repositorio Spring JPA podemos usar la anotación @EnableJpaRepositories y especificar el paquete que contiene las interfaces DAO:

@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.repository") public class PersistenceConfig { ... }

Podemos hacer lo mismo con una configuración XML:

6. Configuración de Java o XML

Ya discutimos con gran detalle cómo configurar JPA en Spring en un artículo anterior. Spring Data también aprovecha el soporte de Spring para la anotación JPA @PersistenceContext . Utiliza esto para conectar el EntityManager al bean de fábrica Spring responsable de crear las implementaciones de DAO reales: JpaRepositoryFactoryBean .

Además de la configuración ya discutida, también necesitamos incluir Spring Data XML Config, si estamos usando XML:

@Configuration @EnableTransactionManagement @ImportResource("classpath*:*springDataConfig.xml") public class PersistenceJPAConfig { ... }

7. Dependencia de Maven

In addition to the Maven configuration for JPA, like in a previous article, we'll add the spring-data-jpa dependency:

 org.springframework.data spring-data-jpa 2.2.7.RELEASE 

8. Using Spring Boot

We can also use the Spring Boot Starter Data JPA dependency that will automatically configure the DataSource for us.

We also need to make sure that the database we want to use is present in the classpath. In our example, we've added the H2 in-memory database:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.6.RELEASE   com.h2database h2 1.4.200 

As a result, just by doing these dependencies, our application is up and running and we can use it for other database operations.

The explicit configuration for a standard Spring application is now included as part of Spring Boot auto-configuration.

We can, of course, modify the auto-configuration by adding our customized explicit configuration.

Spring Boot provides an easy way to do this using properties in the application.properties file:

spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password=sa

In this example, we've changed the connection URL and credentials.

9. Conclusion

This article covered the configuration and implementation of the persistence layer with Spring 5, JPA 2, and Spring Data JPA (part of the Spring Data umbrella project), using both XML and Java-based configuration.

We discussed ways to define more advanced custom queries, as well as transactional semantics, and a configuration with the new jpa namespace. The final result is a new and elegant take on data access with Spring, with almost no actual implementation work.

La implementación de este tutorial de Spring Data JPA se puede encontrar en el proyecto GitHub.