配置
本节介绍通过以下任一方式配置 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、record 类型、注解等飞速发展的时代,新项目通常尽可能多地使用纯 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 Framework 支持在后台线程中初始化 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 是一个合理的默认值,因为它会确保 Spring Data JPA 引导仅在 EntityManagerFactory 的搭建本身耗时超过初始化所有其他应用组件时才等待它。尽管如此,它仍会确保仓库在应用程序发出就绪信号之前被正确初始化和验证。
LAZY 对于测试场景和本地开发是一个不错的选择。一旦您相当确定仓库可以正确引导,或者在测试应用程序其他部分的情况下,为所有仓库运行验证可能会不必要地增加启动时间。对于您只访问应用程序部分功能、可能只需初始化单个仓库的本地开发,情况同样如此。