BootstrapMode for JPA Repositories – JPA存储库的BootstrapMode

最后修改: 2022年 4月 10日

1. Introduction


In this brief tutorial, we’ll focus on the different types of BootstrapMode for JPA repositories that Spring provides for altering the orchestration of their instantiation.


At startup, Spring Data scans for repositories and registers their bean definitions as singleton-scoped beans. During their initialization, repositories obtain an EntityManager immediately. Specifically, they get the JPA metamodel and validate declared queries.

在启动时,Spring Data会扫描存储库并将它们的bean定义注册为单子范围的bean。在初始化过程中,存储库会立即获得一个EntityManager。具体来说,它们会获得JPA元模型并验证已声明的查询。

JPA is bootstrapped synchronously by default. Consequently, the instantiation of repositories is blocked until the bootstrap process completes. As the number of repositories grows, the application could take a long time to start before it begins accepting requests.


2. Different Options for Bootstrapping Repositories


Let’s start by adding the spring-data-jpa dependency. As we are using Spring Boot, we’ll use the corresponding spring-boot-starter-data-jpa dependency:

让我们开始添加spring-data-jpa依赖项。由于我们使用的是Spring Boot,我们将使用相应的spring-boot-starter-data-jpa依赖性。


We can tell Spring to use the default repository bootstrap behavior via a configuration property:


We can do the same by using annotations-based configuration:


@EnableJpaRepositories(bootstrapMode = BootstrapMode.DEFAULT)
public class Application {
    // ...

A third approach, restrained to a single test class, is to use the @DataJpaTest annotation:


@DataJpaTest(bootstrapMode = BootstrapMode.LAZY)
class BootstrapmodeLazyIntegrationTest {
    // ...

For the following examples, we’ll use the @DataJpaTest annotation and explore the different repository bootstrap options.


2.1. Default

2.1 默认情况

The default value for bootstrap mode will instantiate repositories eagerly. Hence, like any other Spring beans, their initialization will occur when injected.

Bootstrap模式的默认值将急切地实例化资源库。因此,像任何其他Spring Bean一样,它们的初始化将在注入时发生

Let’s create a Todo entity:


public class Todo {
    private Long id;
    private String label;

    // standard setters and getters

Next, we’ll need its associated repository. Let’s create one that extends CrudRepository:


public interface TodoRepository extends CrudRepository<Todo, Long> {

Finally, let’s add a test that uses our repository:


class BootstrapmodeDefaultIntegrationTest {

    private TodoRepository todoRepository;

    void givenBootstrapmodeValueIsDefault_whenCreatingTodo_shouldSuccess() {
        Todo todo = new Todo("Something to be done");


After starting our test, let’s check the logs where we’ll find out how Spring bootstrapped our TodoRepository:


[2022-03-22 14:46:47,597]-[main] INFO - Bootstrapping Spring Data JPA repositories in DEFAULT mode.
[2022-03-22 14:46:47,737]-[main] TRACE - Spring Data JPA - Registering repository: todoRepository - Interface: com.baeldung.boot.bootstrapmode.repository.TodoRepository - Factory:
[2022-03-22 14:46:49,718]-[main] DEBUG - Initializing repository instance for com.baeldung.boot.bootstrapmode.repository.TodoRepository…
[2022-03-22 14:46:49,792]-[main] DEBUG - Finished creation of repository instance for com.baeldung.boot.bootstrapmode.repository.TodoRepository.
[2022-03-22 14:46:49,858]-[main] INFO  com.baeldung.boot.bootstrapmode.BootstrapmodeDefaultIntegrationTest - Started BootstrapmodeDefaultIntegrationTest in 3.547 seconds (JVM running for 4.877)

In our example, we initialize repositories early and make them available once the application has started.


2.2. Lazy


By using the lazy BootstrapMode for JPA repositories, Spring registers our repository’s bean definition but does not instantiate it right away. Thus, using the lazy option, the first use triggers its initialization.


Let’s modify our test and apply the lazy option to bootstrapMode:


@DataJpaTest(bootstrapMode = BootstrapMode.LAZY)

Then, let’s launch our test with our fresh configuration, and check the corresponding logs:


[2022-03-22 15:09:01,360]-[main] INFO - Bootstrapping Spring Data JPA repositories in LAZY mode.
[2022-03-22 15:09:01,398]-[main] TRACE - Spring Data JPA - Registering repository: todoRepository - Interface: com.baeldung.boot.bootstrapmode.repository.TodoRepository - Factory:
[2022-03-22 15:09:01,971]-[main] INFO  com.baeldung.boot.bootstrapmode.BootstrapmodeLazyIntegrationTest - Started BootstrapmodeLazyIntegrationTest in 1.299 seconds (JVM running for 2.148)
[2022-03-22 15:09:01,976]-[main] DEBUG$LazyRepositoryInjectionPointResolver - Creating lazy injection proxy for com.baeldung.boot.bootstrapmode.repository.TodoRepository…
[2022-03-22 15:09:02,588]-[main] DEBUG - Initializing repository instance for com.baeldung.boot.bootstrapmode.repository.TodoRepository…

We should pay attention to a couple of drawbacks here:


  • Spring might start accepting requests without having initialized repositories, thereby increasing latency when the first ones are handled.
  • Setting up BootstrapMode to lazy globally is error-prone. Spring will not validate queries and metadata contained in repositories that are not included in our tests.

We should use lazy bootstrapping only during development to avoid deploying an application in production with a potential initialization error. We can elegantly use Spring Profiles for this purpose.

我们应该只在开发过程中使用懒惰引导,以避免在生产中部署应用程序时出现潜在的初始化错误。我们可以优雅地使用Spring Profiles来实现这一目的。

2.3. Deferred


Deferred is the right option to use when bootstrapping JPA asynchronously. As a result, repositories don’t wait for the EntityManagerFactory‘s initialization.


Let’s declare an AsyncTaskExecutor in a configuration class by using ThreadPoolTaskExecutor – one of its Spring implementations – and override the submit method, which returns a Future:


AsyncTaskExecutor delayedTaskExecutor() {
    return new ThreadPoolTaskExecutor() {
        public <T> Future<T> submit(Callable<T> task) {
            return super.submit(() -> {

Next, let’s add an EntityManagerFactory bean to our configuration as shown in our Guide to JPA with Spring, and indicate that we want to use our asynchronous executor for background bootstrapping:

接下来,让我们将EntityManagerFactory Bean添加到我们的配置中,如我们的《JPA与Spring指南》所示,并指出我们希望使用我们的异步执行器来进行后台引导。

LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, AsyncTaskExecutor delayedTaskExecutor) {
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

    factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    Map<String, Object> properties = new HashMap<>();
    properties.put("", "create-drop");
    return factory;

Finally, let’s modify our test to enable deferred bootstrap mode:


@DataJpaTest(bootstrapMode = BootstrapMode.DEFERRED)

Let’s launch our test again and check the logs:


[2022-03-23 10:31:16,513]-[main] INFO - Bootstrapping Spring Data JPA repositories in DEFERRED mode.
[2022-03-23 10:31:16,543]-[main] TRACE - Spring Data JPA - Registering repository: todoRepository - Interface: com.baeldung.boot.bootstrapmode.repository.TodoRepository - Factory:
[2022-03-23 10:31:16,545]-[main] DEBUG - Registering deferred repository initialization listener.
[2022-03-23 10:31:17,108]-[main] INFO - Triggering deferred initialization of Spring Data repositories…
[2022-03-23 10:31:22,538]-[main] DEBUG - Initializing repository instance for com.baeldung.boot.bootstrapmode.repository.TodoRepository…
[2022-03-23 10:31:22,572]-[main] INFO  com.baeldung.boot.bootstrapmode.BootstrapmodeDeferredIntegrationTest - Started BootstrapmodeDeferredIntegrationTest in 6.769 seconds (JVM running for 7.519)

In this example, the application context bootstrap completion triggers the repositories’ initialization. In short, Spring marks repositories as lazy and registers a DeferredRepositoryInitializationListener bean. When the ApplicationContext fires a ContextRefreshedEvent, it initializes all repositories.

在这个例子中,应用程序上下文的引导完成会触发存储库的初始化。简而言之,Spring将存储库标记为懒惰,并注册了一个DeferredRepositoryInitializationListener bean。当ApplicationContext触发ContextRefreshedEvent时,它将初始化所有存储库。

Therefore, Spring Data initializes repositories and validates their included queries and metadata before the application startup.

因此,Spring Data在应用程序启动前初始化存储库并验证其包含的查询和元数据

3. Conclusion


In this article, we looked at various ways to initialize JPA repositories and in which cases to use them.
As usual, all the code samples used in this article can be found over on GitHub.