配置
本节介绍通过以下方式配置 Spring Data JPA:
-
“基于注解的配置”(Java 配置)
-
“Spring 命名空间”(XML 配置)
基于注解的配置
Spring Data JPA 仓库支持可以通过 JavaConfig 或自定义 XML 命名空间来激活,如下例所示:
示例 1. 使用 JavaConfig 配置 Spring Data JPA 仓库
@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-jdbc
的 EmbeddedDatabaseBuilder
API 设置了一个嵌入式 HSQL 数据库。然后,Spring Data 设置了一个 EntityManagerFactory
,并使用 Hibernate 作为示例的持久化提供程序。这里声明的最后一个基础设施组件是 JpaTransactionManager
。最后,示例通过使用 @EnableJpaRepositories
注解激活了 Spring Data JPA 仓库,该注解本质上携带了与 XML 命名空间相同的属性。如果没有配置基础包,它将使用配置类所在的包。
Spring 命名空间
Spring Data 的 JPA 模块包含一个自定义命名空间,允许定义仓库 Bean。它还包含一些特定于 JPA 的特性和元素属性。通常,可以通过使用 repositories
元素来设置 JPA 仓库,如下例所示:
示例 2. 使用命名空间设置 JPA 仓库
<?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
层次结构。
自定义命名空间属性
除了 repositories
元素的默认属性外,JPA 命名空间还提供了额外的属性,以便您能够更详细地控制存储库的设置:
表 1. repositories
元素的自定义 JPA 特定属性
|
|
| entity-manager-factory-ref
| 显式指定要与 repositories
元素检测到的存储库一起使用的 EntityManagerFactory
。通常在应用程序中使用多个 EntityManagerFactory
bean 时使用。如果未配置,Spring Data 会自动在 ApplicationContext
中查找名为 entityManagerFactory
的 EntityManagerFactory
bean。 |
| transaction-manager-ref
| 显式指定要与 repositories
元素检测到的存储库一起使用的 PlatformTransactionManager
。通常仅在配置了多个事务管理器或 EntityManagerFactory
bean 时才需要。默认使用当前 ApplicationContext
中定义的单个 PlatformTransactionManager
。 |
如果未定义显式的 transaction-manager-ref
,Spring Data JPA 需要一个名为 transactionManager
的 PlatformTransactionManager
bean。
引导模式
默认情况下,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
时触发仓库初始化,以便在应用程序完全启动之前对仓库进行验证。
推荐
如果你没有使用异步 JPA 引导,请坚持使用默认的引导模式。
如果你以异步方式引导 JPA,那么 DEFERRED
是一个合理的默认选择,因为它会确保只有在 EntityManagerFactory
的设置时间比初始化所有其他应用程序组件更长时,Spring Data JPA 的引导才会等待。尽管如此,它仍然会确保在应用程序发出启动信号之前,所有的仓库都已正确初始化和验证。
LAZY
是测试场景和本地开发的一个不错的选择。一旦你相当确定仓库可以正确引导,或者在你测试应用程序的其他部分时,对所有仓库运行验证可能会不必要地增加启动时间。这同样适用于本地开发,在这种情况下,你只访问可能需要初始化单个仓库的应用程序部分。