配置

本節描述瞭如何透過以下方式配置 Spring Data JPA:

基於註解的配置

透過 JavaConfig 和自定義 XML namespace 都可以啟用 Spring Data JPA repository 支援,如下例所示

示例 1. 使用 JavaConfig 的 Spring Data JPA repositories
@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 repositories,該註解本質上與 XML namespace 具有相同的屬性。如果未配置 base package,則使用配置類所在的 package。

Spring Namespace

Spring Data 的 JPA 模組包含一個自定義 namespace,允許定義 repository bean。它還包含一些 JPA 特有的特性和元素屬性。通常,可以使用 repositories 元素來設定 JPA repositories,如下例所示

示例 2. 使用 namespace 設定 JPA repositories
<?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 時代,record types、註解等更多特性出現,新專案通常儘可能使用純 Java。雖然目前沒有立即移除 XML 支援的計劃,但一些最新的特性可能無法透過 XML 使用。

使用 repositories 元素可以啟用所有帶有 @Repository 註解的 bean 的持久化異常轉換,以便將 JPA 持久化提供者丟擲的異常轉換為 Spring 的 DataAccessException 層次結構。

自定義 Namespace 屬性

除了 repositories 元素的預設屬性外,JPA namespace 還提供額外的屬性,讓您對 repository 的設定進行更精細的控制

表 1. repositories 元素的 JPA 特有自定義屬性

entity-manager-factory-ref

顯式關聯 EntityManagerFactory 以用於 repositories 元素檢測到的 repositories。通常在應用程式中使用多個 EntityManagerFactory bean 時使用。如果未配置,Spring Data 會自動在 ApplicationContext 中查詢名稱為 entityManagerFactoryEntityManagerFactory bean。

transaction-manager-ref

顯式關聯 PlatformTransactionManager 以用於 repositories 元素檢測到的 repositories。通常僅在配置了多個事務管理器或 EntityManagerFactory bean 時才需要。預設為當前 ApplicationContext 中定義的單個 PlatformTransactionManager

如果未定義顯式的 transaction-manager-ref,Spring Data JPA 需要一個名為 transactionManagerPlatformTransactionManager bean。

引導模式 (Bootstrap Mode)

預設情況下,Spring Data JPA repositories 是預設的 Spring bean。它們是單例範圍並急切初始化。在啟動期間,它們已經與 JPA EntityManager 互動以進行驗證和元資料分析。Spring Framework 支援在後臺執行緒中初始化 JPA EntityManagerFactory,因為該過程通常會佔用 Spring 應用程式大量的啟動時間。為了有效利用後臺初始化,我們需要確保 JPA repositories 儘可能晚地初始化。

從 Spring Data JPA 2.1 開始,您現在可以配置一個 BootstrapMode(透過 @EnableJpaRepositories 註解或 XML namespace),其取值如下

  • DEFAULT (預設) — Repositories 會被急切例項化,除非顯式註解了 @Lazy。懶載入僅在沒有客戶端 bean 需要 repository 例項時才有效,因為這會需要 repository bean 的初始化。

  • LAZY — 隱式宣告所有 repository bean 為懶載入,並建立懶載入初始化代理注入到客戶端 bean 中。這意味著,如果客戶端 bean 只是將例項儲存在一個欄位中並且在初始化期間沒有使用 repository,則 repository 將不會被例項化。Repository 例項將在與 repository 首次互動時進行初始化和驗證。

  • DEFERRED — 操作模式與 LAZY 基本相同,但在響應 ContextRefreshedEvent 時觸發 repository 初始化,以便在應用程式完全啟動之前驗證 repositories。

建議

如果您不使用非同步 JPA 引導,請堅持使用預設的引導模式。

如果您非同步引導 JPA,DEFERRED 是一個合理的預設值,因為它會確保 Spring Data JPA 引導僅在 EntityManagerFactory 本身設定所需時間長於初始化所有其他應用程式元件時才等待。儘管如此,它仍確保在應用程式發出啟動訊號之前 repositories 已正確初始化和驗證。

LAZY 是測試場景和本地開發的一個不錯的選擇。一旦您相當確定 repositories 可以正確引導,或者在測試應用程式其他部分的情況下,對所有 repositories 執行驗證可能會不必要地增加啟動時間。對於您只訪問應用程式部分(可能需要初始化單個 repository)的本地開發也是如此。