Configuration

Java 配置使用 @EnableJpaRepositories 等注释,而 XML 配置使用自定义命名空间和 repositories 元素。此外,BootstrapMode 可以用来控制存储库在启动时的初始化方式,默认情况下它们是 eager 初始化的。对于异步 JPA 引导,DEFERRED 模式是推荐的,而对于测试场景和本地开发,LAZY 模式是合适的。

本节描述了通过以下方式配置 Spring Data JPA:

This section describes configuring Spring Data JPA through either:

Annotation-based Configuration

Spring Data JPA 存储库支持可以通过 JavaConfig 和自定义 XML 命名空间激活,如下例所示:

The Spring Data JPA repositories support can be activated through both JavaConfig as well as a custom XML namespace, as shown in the following example:

Example 1. Spring Data JPA repositories using JavaConfig
@Configuration
@EnableJpaRepositories
@EnableTransactionManagement
class ApplicationConfig {

  @Bean
  public DataSource dataSource() {

    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    return builder.setType(EmbeddedDatabaseType.HSQL).build();
  }

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.acme.domain");
    factory.setDataSource(dataSource());
    return factory;
  }

  @Bean
  public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {

    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(entityManagerFactory);
    return txManager;
  }
}

您必须直接创建 LocalContainerEntityManagerFactoryBean 而不是 EntityManagerFactory,因为前者除了创建 EntityManagerFactory 之外,还参与异常转换机制。

You must create LocalContainerEntityManagerFactoryBean and not EntityManagerFactory directly, since the former also participates in exception translation mechanisms in addition to creating EntityManagerFactory.

前面的配置类通过使用 spring-jdbcEmbeddedDatabaseBuilder API 设置了嵌入式 HSQL 数据库。然后,Spring Data 设置了一个 EntityManagerFactory,并将 Hibernate 用作示例持久化提供程序。此处声明的最后一个基础设施组件是 JpaTransactionManager。最后,示例使用 @EnableJpaRepositories 注释激活了 Spring Data JPA 存储库,该注释本质上与 XML 命名空间具有相同的属性。如果没有配置基包,则会使用配置类驻留的基包。

The preceding configuration class sets up an embedded HSQL database by using the EmbeddedDatabaseBuilder API of spring-jdbc. Spring Data then sets up an EntityManagerFactory and uses Hibernate as the sample persistence provider. The last infrastructure component declared here is the JpaTransactionManager. Finally, the example activates Spring Data JPA repositories by using the @EnableJpaRepositories annotation, which essentially carries the same attributes as the XML namespace. If no base package is configured, it uses the one in which the configuration class resides.

Spring Namespace

Spring Data 的 JPA 模块包含一个自定义命名空间,它允许定义存储库 bean。它还包含特定于 JPA 的某些功能和元素属性。通常,可以使用 repositories 元素来设置 JPA 存储库,如下例所示:

The JPA module of Spring Data contains a custom namespace that allows defining repository beans. It also contains certain features and element attributes that are special to JPA. Generally, the JPA repositories can be set up by using the repositories element, as shown in the following example:

Example 2. Setting up JPA repositories by using the namespace
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jpa="http://www.springframework.org/schema/data/jpa"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/jpa
    https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

  <jpa:repositories base-package="com.acme.repositories" />

</beans>

哪个更好,JavaConfig 还是 XML?XML 是很久以前 Spring 的配置方式。在当今 Java 快速发展、记录类型、注解等时代,新项目通常尽可能多地使用纯 Java。虽然没有立即计划删除 XML 支持,但某些最新特性可能无法通过 XML 获得。

Which is better, JavaConfig or XML? XML is how Spring was configured long ago. In today’s era of fast-growing Java, record types, annotations, and more, new projects typically use as much pure Java as possible. While there is no immediate plan to remove XML support, some of the newest features MAY not be available through XML.

使用 repositories 元素可以为所有使用 @Repository 注释的 bean 激活持久化异常转换,以便将 JPA 持久化提供程序抛出的异常转换为 Spring 的 DataAccessException 层次结构。

Using the repositories element it activates persistence exception translation for all beans annotated with @Repository, to let exceptions being thrown by the JPA persistence providers be converted into Spring’s DataAccessException hierarchy.

Custom Namespace Attributes

除了 repositories 元素的默认属性之外,JPA 命名空间还提供了其他属性,让您可以更详细地控制存储库的设置:

Beyond the default attributes of the repositories element, the JPA namespace offers additional attributes to let you gain more detailed control over the setup of the repositories:

Table 1. Custom JPA-specific attributes of the repositories element

entity-manager-factory-ref

Explicitly wire the EntityManagerFactory to be used with the repositories being detected by the repositories element. Usually used if multiple EntityManagerFactory beans are used within the application. If not configured, Spring Data automatically looks up the EntityManagerFactory bean with the name entityManagerFactory in the ApplicationContext.

transaction-manager-ref

Explicitly wire the PlatformTransactionManager to be used with the repositories being detected by the repositories element. Usually only necessary if multiple transaction managers or EntityManagerFactory beans have been configured. Default to a single defined PlatformTransactionManager inside the current ApplicationContext.

如果未定义显式的 transaction-manager-ref,则 Spring Data JPA 要求存在一个名为 transactionManagerPlatformTransactionManager bean。

Spring Data JPA requires a PlatformTransactionManager bean named transactionManager to be present if no explicit transaction-manager-ref is defined.

Bootstrap Mode

默认情况下,Spring Data JPA 存储库是默认的 Spring bean。它们的范围为单例且急于初始化。在启动过程中,它们已经与 JPA EntityManager 交互,用于验证和元数据分析目的。Spring 框架支持在后台线程中初始化 JPA EntityManagerFactory,因为该过程通常会占用 Spring 应用程序中大量的启动时间。为了有效地使用该后台初始化,我们需要确保 JPA 存储库尽可能晚地初始化。

By default, Spring Data JPA repositories are default Spring beans. They are singleton scoped and eagerly initialized. During startup, they already interact with the JPA EntityManager for verification and metadata analysis purposes. Spring Framework supports the initialization of the JPA EntityManagerFactory in a background thread because that process usually takes up a significant amount of startup time in a Spring application. To make use of that background initialization effectively, we need to make sure that JPA repositories are initialized as late as possible.

从 Spring Data JPA 2.1 开始,您现在可以配置一个 BootstrapMode(通过 @EnableJpaRepositories 注释或 XML 命名空间),它采用以下值:

As of Spring Data JPA 2.1 you can now configure a BootstrapMode (either via the @EnableJpaRepositories annotation or the XML namespace) that takes the following values:

  • DEFAULT (default) — Repositories are instantiated eagerly unless explicitly annotated with @Lazy. The lazification only has effect if no client bean needs an instance of the repository as that will require the initialization of the repository bean.

  • LAZY — Implicitly declares all repository beans lazy and also causes lazy initialization proxies to be created to be injected into client beans. That means, that repositories will not get instantiated if the client bean is simply storing the instance in a field and not making use of the repository during initialization. Repository instances will be initialized and verified upon first interaction with the repository.

  • DEFERRED — Fundamentally the same mode of operation as LAZY, but triggering repository initialization in response to an ContextRefreshedEvent so that repositories are verified before the application has completely started.

Recommendations

如果您不使用异步 JPA 引导,请坚持默认引导模式。

If you’re not using asynchronous JPA bootstrap stick with the default bootstrap mode.

如果您异步引导 JPA,那么 DEFERRED 是一个合理的默认值,因为它将确保 Spring Data JPA 引导仅等待 EntityManagerFactory 设置,前提是它本身花费的时间超过所有其他应用程序组件的初始化时间。但是,它确保在应用程序发出启动信号之前,存储库已正确初始化和验证。

In case you bootstrap JPA asynchronously, DEFERRED is a reasonable default as it will make sure the Spring Data JPA bootstrap only waits for the EntityManagerFactory setup if that itself takes longer than initializing all other application components. Still, it makes sure that repositories are properly initialized and validated before the application signals it’s up.

对于测试场景和本地开发,LAZY 是一个不错的选择。一旦您非常确定存储库可以正确引导,或者在您测试应用程序的其他部分时,为所有存储库运行验证可能会不必要地增加启动时间。在本地开发中也适用此原则,在本地开发中,您只访问可能需要初始化单个存储库的应用程序部分。

LAZY is a decent choice for testing scenarios and local development. Once you are pretty sure that repositories can properly bootstrap, or in cases where you are testing other parts of the application, running verification for all repositories might unnecessarily increase the startup time. The same applies to local development in which you only access parts of the application that might need to have a single repository initialized.