Configuration

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

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

Annotation-based Configuration

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

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 之外,还参与异常转换机制。

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

Spring Namespace

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

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 获得。

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

Custom Namespace Attributes

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

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

entity-manager-factory-ref

明确连接 EntityManagerFactory 以便与 repositories 元素检测到的存储库一起使用。通常在应用程序内使用多个 EntityManagerFactory bean 时使用。如果未配置,Spring Data 会在 ApplicationContext 中自动查找名为 entityManagerFactoryEntityManagerFactory Bean。

transaction-manager-ref

明确连接 PlatformTransactionManager 以便与 repositories 元素检测到的存储库一起使用。通常只有在配置了多个事务管理器或 EntityManagerFactory bean 时才需要这样做。默认为在当前 ApplicationContext 中定义的单个 PlatformTransactionManager

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

Bootstrap Mode

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

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

  • DEFAULT(默认)- 除非明确标注 @Lazy,否则仓库将被急切地实例化。只有当没有客户端 Bean 需要仓库实例时,懒化才会起作用,因为这需要仓库 Bean 的初始化。

  • LAZY - 隐式声明所有仓库 Bean 延迟,并导致创建延迟初始化代理以注入到客户端 Bean。这意味着,如果客户端 Bean 只是将实例存储在字段中,并且在初始化期间不会使用仓库,则仓库不会被实例化。仓库实例将在首次与仓库交互时进行初始化和验证。

  • DEFERRED - 与 LAZY 的操作模式基本相同,但触发仓库初始化以响应 ContextRefreshedEvent,以便在应用程序完全启动之前验证仓库。

Recommendations

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

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

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