La API de persistencia de Java es una tecnología estándar que le permite "asignar" objetos a bases de datos relacionales. El modelo POM spring-boot-starter-data-jpa le permite comenzar rápidamente. Proporciona las siguientes dependencias clave:

  • Hibernate es una de las implementaciones JPA más populares.

  • Spring Data JPA: ayuda a implementar repositorios basados en JPA.

  • Spring ORM: la principal herramienta de soporte ORM de Spring Framework.

Tradicionalmente, las clases de "entidad" JPA se definen en el archivo persistence.xml. En Spring Boot, este archivo no es necesario; en su lugar se utiliza Entity Scanning. De forma predeterminada, la búsqueda se realiza en todos los paquetes debajo de la clase de configuración principal (el que está anotado con @EnableAutoConfiguration o @SpringBootApplication).

Se tienen en cuenta todas las clases anotadas con @Entity, @Embeddable o @MappedSuperclass. Una clase de entidad típica se parece al siguiente ejemplo:

Java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class City implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String state;
    // ... miembros adicionales, que a menudo contienen asignaciones de anotaciones @OneToMany
    protected City() {
        // constructor sin argumentos requerido por la especificación JPA
        // protegido porque no debe usarse directamente
    }
    public City(String name, String state) {
        this.name = name;
        this.state = state;
    }
    public String getName() {
        return this.name;
    }
    public String getState() {
        return this.state;
    }
    // ... etc.
}
Kotlin

import java.io.Serializable
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
@Entity
class City : Serializable {
    @Id
    @GeneratedValue
    private val id: Long? = null
    @Column(nullable = false)
    var name: String? = null
        private set
    // ... etc.
    @Column(nullable = false)
    var state: String? = null
        private set
    // ... additional members, often containing @OneToMany annotation mappings
    protected constructor() {
        // miembros adicionales, que a menudo contienen asignaciones de anotaciones @OneToMany
        // protegido porque no debe usarse directamente
    }
    constructor(name: String?, state: String?) {
        this.name = name
        this.state = state
    }
}
Puede configurar las ubicaciones que se escanearán en busca de entidades utilizando la anotación @EntityScan.

Repositorios JPA de datos de Spring

Los repositorios Spring Data JPA son interfaces que se pueden definir para acceder a los datos. Las consultas JPA se crean automáticamente en función de los nombres de los métodos. Por ejemplo, la interfaz CityRepository podría declarar un método findAllByState(String state) para buscar todas las ciudades en un estado determinado.

Para consultas más complejas, puede anotar el método utilizando la anotación Query de Spring Data.

Los repositorios de Spring Data normalmente se amplían utilizando las interfaces Repository o CrudRepository. Si utiliza la configuración automática, los repositorios se buscan desde el paquete que contiene la clase de configuración principal (la que está anotada con @EnableAutoConfiguration o @SpringBootApplication) y hacia abajo en la jerarquía.

El siguiente ejemplo muestra una definición de interfaz típica para interactuar con un repositorio de Spring Data:

Java
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
    Page<City> findAll(Pageable pageable);
    City findByNameAndStateAllIgnoringCase(String name, String state);
}
Kotlin
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
interface CityRepository : Repository<City?, Long?> {
    fun findAll(pageable: Pageable?): Page<City?>?
    fun findByNameAndStateAllIgnoringCase(name: String?, state: String?): City?
}

Los repositorios Spring Data JPA admiten tres modos de arranque diferentes: predeterminado, retrasado y diferido. Para habilitar la carga diferida o la carga diferida, establezca la propiedad spring.data.jpa.repositories.bootstrap-mode en deferred o lazy respectivamente. Cuando se realiza una carga diferida o retrasada, el EntityManagerFactoryBuilder configurado automáticamente utilizará el AsyncTaskExecutor del contexto, si está presente, como ejecutor de carga. Si hay más de un ejecutor, se utilizará el denominado applicationTaskExecutor.

Al utilizar la carga retrasada o la carga diferida, debe asegurarse de que el acceso a la infraestructura JPA se proporcione con un retraso después de la etapa de carga inicial del contexto de la aplicación. Puede utilizar SmartInitializingSingleton para llamar a cualquier inicialización que requiera el marco JPA. Para los componentes JPA (como los convertidores) de los que se crean instancias como Spring beans, utilice ObjectProvider para diferir la resolución de dependencias, si corresponde.

Repositorios de Spring Data Envers

Si Spring Data Envers está disponible, los repositorios JPA se configurarán automáticamente para admitir consultas típicas de Envers.

Para utilizar Spring Data Envers, asegúrese de que el repositorio esté extendido desde RevisionRepository, como se muestra en el siguiente ejemplo:

Java
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.history.RevisionRepository;
public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {
    Page<Country> findAll(Pageable pageable);
}
Kotlin
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.Repository
import org.springframework.data.repository.history.RevisionRepository
interface CountryRepository :
        RevisionRepository<Country?, Long?, Int>,
        Repository<Country?, Long?> {
    fun findAll(pageable: Pageable?): Page<Country?>?
}

Crear y eliminar bases de datos JPA

De forma predeterminada, las bases de datos JPA se crean automáticamente sólo si utiliza una base de datos integrada (H2, HSQL o Derby). Puede configurar explícitamente los ajustes de JPA utilizando las propiedades spring.jpa.*. Por ejemplo, para crear y eliminar tablas, puede agregar la siguiente línea a application.properties:

Propiedades
spring.jpa.hibernate.ddl-auto=create-drop
Yaml
primavera:
  jpa:
    hibernate.ddl-auto: "crear-soltar"
El nombre de la propiedad nativa de Hibernate para este procedimiento (si lo recuerda bien, por supuesto) es hibernate.hbm2ddl.auto. Puede configurarlo junto con otras propiedades nativas de Hibernate usando spring.jpa.properties.* (el prefijo se elimina antes de agregarlo al administrador de entidades). La siguiente línea muestra un ejemplo de configuración de propiedades JPA para Hibernate:
Propiedades
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
Yaml
primavera:
  jpa:
    propiedades:
      hibernar:
        "globally_quoted_identifiers": "verdadero"

La línea del ejemplo anterior pasa el valor true para la propiedad hibernate.globally_quoted_identifiers al administrador de entidades de Hibernate.

De forma predeterminada, la ejecución (o validación) de DDL se difiere hasta que se inicie ApplicationContext. También hay un indicador spring.jpa.generate-ddl, pero no se usa si la configuración automática de Hibernate está activa, ya que la configuración ddl-auto es más precisa.

Abrir EntityManager en una vista

Si está ejecutando una aplicación web, Spring Boot registra de forma predeterminada OpenEntityManagerInViewInterceptor para aplicar el patrón Open EntityManager in View para permitir la carga diferida en vistas web. Si no necesita esta lógica operativa, debe configurar spring.jpa.open-in-view en false en application.properties.