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:
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.
}
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
}
}
@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:
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);
}
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:
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);
}
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
:
spring.jpa.hibernate.ddl-auto=create-drop
primavera:
jpa:
hibernate.ddl-auto: "crear-soltar"
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:
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
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
.