The Java Persistence API is a standard technology that allows you to "map" objects to relational databases. The
spring-boot-starter-data-jpa
POM model allows you to get started quickly. It provides the following key
dependencies:
-
Hibernate is one of the most popular JPA implementations.
-
Spring Data JPA: Helps implement JPA-based repositories.
-
Spring ORM: The primary ORM support tool from the Spring Framework.
Traditionally, JPA "entity" classes are defined in the persistence.xml
file. In Spring Boot, this file
is not required; Entity Scanning is used instead. By default, the search is performed in all packages below the main
configuration class (the one annotated with @EnableAutoConfiguration
or
@SpringBootApplication
).
Any classes annotated with @Entity
, @Embeddable
or @MappedSuperclass
are taken
into account. A typical entity class looks like the following example:
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;
// ... additional members, often containing @OneToMany annotation mappings
protected City() {
// no-argument constructor required by the JPA specification
// protected because it's not meant to be used directly
}
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() {
// no-argument constructor required by the JPA specification
// protected because it's not meant to be used directly
}
constructor(name: String?, state: String?) {
this.name = name
this.state = state
}
}
@EntityScan
annotation.
Spring Data JPA Repositories
Spring Data JPA repositories are interfaces that can be defined to access data. JPA queries are created automatically
based on method names. For example, the CityRepository
interface might declare a findAllByState(String
state)
method to find all cities in a given state.
For more complex queries, you can annotate the method using the Query
annotation from Spring Data.
Spring Data repositories are typically extended using the Repository
or CrudRepository
interfaces. If you use autoconfiguration, the repositories are searched from the package containing the main
configuration class (the one annotated with @EnableAutoConfiguration
or
@SpringBootApplication
) and down the hierarchy.
The following example shows a typical interface definition for interacting with a Spring Data repository:
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?
}
Spring Data JPA repositories support three different bootstrap modes: default, delayed, and lazy. To enable deferred
loading or lazy loading, set the spring.data.jpa.repositories.bootstrap-mode
property to
deferred
or lazy
respectively. When lazy loading or delayed loading, the autoconfigured
EntityManagerFactoryBuilder
will use the context's AsyncTaskExecutor
, if present, as the
load executor. If there is more than one executor, the one named applicationTaskExecutor
will be used.
When using delayed loading or lazy loading, you should ensure that access to the JPA infrastructure is provided
with a delay after the application context initial loading stage. You can use
SmartInitializingSingleton
to call any initialization that requires the JPA framework. For JPA
components (such as converters) that are instantiated as Spring beans, use ObjectProvider
to defer
dependency resolution, if any.
Spring Data Envers Repositories
If Spring Data Envers is available, JPA repositories will be automatically configured to support typical Envers queries.
To use Spring Data Envers, ensure that the repository is extended from RevisionRepository
, as shown in
the following example:
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?>?
}
Creating and deleting JPA databases
By default, JPA databases are created automatically only if you use an embedded database (H2, HSQL
or Derby). You can explicitly configure JPA settings using the spring.jpa.*
properties. For example, to
create and delete tables, you can add the following line to application.properties
:
spring.jpa.hibernate.ddl-auto=create-drop
spring:
jpa:
hibernate.ddl-auto: "create-drop"
hibernate.hbm2ddl.auto
. You can set it along with other native Hibernate properties
using spring.jpa.properties.*
(the prefix is removed before adding it to the entity manager). The
following line shows an example of setting JPA properties for Hibernate:
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
spring:
jpa:
properties:
hibernate:
"globally_quoted_identifiers": "true"
The line in the previous example passes the value true
for the hibernate.globally_quoted_identifiers
property to the Hibernate entity manager.
By default, DDL execution (or validation) is deferred until the ApplicationContext
is launched. There is
also a spring.jpa.generate-ddl
flag, but it is not used if Hibernate autoconfiguration is active, since
the ddl-auto
settings are more precise.
Opening EntityManager in a View
If you are running a web application, Spring Boot by default registers
OpenEntityManagerInViewInterceptor
to apply the Open EntityManager in View pattern to enable lazy
loading in web views. If you do not require this operating logic, then you should set
spring.jpa.open-in-view
to false
in application.properties
.