此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Boot 4.0.4!spring-doc.cadn.net.cn

数据库初始化

一个SQL数据库可以根据你的技术栈以不同的方式初始化。 当然,你也可以手动进行,前提是数据库是一个独立的进程。 建议对模式生成使用单一机制。spring-doc.cadn.net.cn

使用 Hibernate 初始化数据库

您可以设置 spring.jpa.hibernate.ddl-auto 来控制 Hibernate 的数据库初始化。 支持的值有 nonevalidateupdatecreatecreate-drop。 Spring Boot 会根据您是否使用嵌入式数据库为您选择一个默认值。 通过查看 Connection 类型和 JDBC URL 来识别嵌入式数据库。 hsqldbh2derby 是嵌入式数据库,其他则不是。 如果识别出嵌入式数据库且未检测到架构管理器(Flyway 或 Liquibase),则 ddl-auto 默认为 create-drop。 在所有其他情况下,它默认为 nonespring-doc.cadn.net.cn

从内存数据库切换到“真实”数据库时,请务必注意,不要对新平台中表和数据的存在做出假设。 您必须显式设置 ddl-auto,或使用其他机制之一来初始化数据库。spring-doc.cadn.net.cn

你可以通过启用 org.hibernate.SQL 日志记录器来输出架构创建。 如果你启用 调试模式,这会自动为你完成。

此外,如果Hibernate从头开始创建模式(即,如果将ddl-auto属性设置为createcreate-drop),则在启动时会执行类路径根目录下的名为import.sql的文件。 这在演示和测试时可能很有用,但如果你小心的话,可能不是你希望在生产环境中放在类路径中的内容。 这是Hibernate的功能(与Spring无关)。spring-doc.cadn.net.cn

使用基本 SQL 脚本初始化数据库

Spring Boot 可以自动创建您的 JDBC DataSource 或 R2DBC ConnectionFactory 的模式(DDL 脚本),并初始化其数据(DML 脚本)。spring-doc.cadn.net.cn

默认情况下,它从 optional:classpath*:schema.sql 加载模式脚本,从 optional:classpath*:data.sql 加载数据脚本。 这些模式和数据脚本的位置可以分别使用 spring.sql.init.schema-locationsspring.sql.init.data-locations 进行自定义。 optional: 前缀表示即使文件不存在,应用程序也会启动。 若要在文件缺失时导致应用程序启动失败,请移除 optional: 前缀。spring-doc.cadn.net.cn

此外,Spring Boot 还会处理 optional:classpath*:schema-${platform}.sqloptional:classpath*:data-${platform}.sql 文件(如果存在),其中 ${platform}spring.sql.init.platform 的值。 这允许您在必要时切换到特定于数据库的脚本。 例如,您可以选择将其设置为数据库的提供商名称(hsqldbh2oraclemysqlpostgresql 等)。spring-doc.cadn.net.cn

默认情况下,仅在使用嵌入式内存数据库时才会执行 SQL 数据库初始化。 要始终初始化 SQL 数据库(无论其类型如何),请将 spring.sql.init.mode 设置为 always。 同样,要禁用初始化,请将 spring.sql.init.mode 设置为 never。 默认情况下,Spring Boot 会启用其基于脚本的数据库初始化器的快速失败(fail-fast)功能。 这意味着,如果脚本引发异常,应用程序将无法启动。 您可以通过设置 spring.sql.init.continue-on-error 来调整该行为。spring-doc.cadn.net.cn

默认情况下,基于脚本的 DataSource 初始化会在创建任何 JPA EntityManagerFactory Bean 之前执行。 schema.sql 可用于为 JPA 管理的实体创建模式,而 data.sql 可用于填充数据。 虽然我们不建议使用多种数据源初始化技术,但如果您希望基于脚本的 DataSource 初始化能够基于 Hibernate 执行的模式创建进行构建,请将 spring.jpa.defer-datasource-initialization 设置为 true。 这将延迟数据源初始化,直到所有 EntityManagerFactory Bean 创建并初始化之后。 随后可以使用 schema.sql 对 Hibernate 执行的任何模式创建进行补充,并使用 data.sql 填充数据。spring-doc.cadn.net.cn

初始化脚本支持使用 -- 表示单行注释,使用 /* */ 表示块注释。 不支持其他注释格式。

如果您使用的是像 Flyway 或 Liquibase 这样的高级数据库迁移工具,应该单独使用它们来创建和初始化模式。 不建议将基本的 schema.sqldata.sql 脚本与 Flyway 或 Liquibase 一起使用,并且在未来的版本中将不再支持。spring-doc.cadn.net.cn

如果您需要使用更高级的数据库迁移工具来初始化测试数据,请参阅关于 FlywayLiquibase 的章节。spring-doc.cadn.net.cn

初始化 Spring Batch 数据库

如果使用 Spring Batch,它会为大多数流行的数据库平台预先打包了 SQL 初始化脚本。 Spring Boot 可以检测您的数据库类型并在启动时执行这些脚本。 如果您使用的是嵌入式数据库,默认情况下会这样做。 您还可以如下面的示例所示,为任何数据库类型启用此功能:spring-doc.cadn.net.cn

spring.batch.jdbc.initialize-schema=always
spring:
  batch:
    jdbc:
      initialize-schema: "always"

您也可以通过将 spring.batch.jdbc.initialize-schema 设置为 never 来显式关闭初始化。spring-doc.cadn.net.cn

使用更高级的数据库迁移工具

Spring Boot 支持两种更高级别的迁移工具:FlywayLiquibasespring-doc.cadn.net.cn

在启动时执行 Flyway 数据库迁移

要自动在启动时运行 Flyway 数据库迁移,请将适当的 Flyway 模块添加到您的类路径中。 内存数据库和基于文件的数据库由 org.flywaydb:flyway-core 支持。 否则,需要一个特定于数据库的模块。 例如,与 PostgreSQL 一起使用 org.flywaydb:flyway-database-postgresql,与 MySQL 一起使用 org.flywaydb:flyway-mysql。 有关更多详细信息,请参阅 Flyway 文档spring-doc.cadn.net.cn

通常,迁移脚本的形式为 V<VERSION>__<NAME>.sql(其中 <VERSION> 是一个以下划线分隔的版本号,例如“1”或“2_1”)。 默认情况下,它们位于名为 classpath:db/migration 的目录中,但你可以通过设置 spring.flyway.locations 来修改该位置。 这是一个由一个或多个 classpath:filesystem: 位置组成的逗号分隔列表。 例如,以下配置将在默认的类路径位置和 /opt/migration 目录中搜索脚本:spring-doc.cadn.net.cn

spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
spring:
  flyway:
    locations: "classpath:db/migration,filesystem:/opt/migration"

您还可以添加一个特殊的 {vendor} 占位符,以使用特定于提供商的脚本。 假设如下:spring-doc.cadn.net.cn

spring.flyway.locations=classpath:db/migration/{vendor}
spring:
  flyway:
    locations: "classpath:db/migration/{vendor}"

前面的配置没有使用 db/migration,而是根据数据库类型设置要使用的目录(例如,MySQL 为 db/migration/mysql)。 支持的数据库列表可在 DatabaseDriver 中查看。spring-doc.cadn.net.cn

迁移也可以用 Java 编写。 Flyway 将使用任何实现 JavaMigration 的 Bean 进行自动配置。spring-doc.cadn.net.cn

FlywayProperties 提供了 Flyway 的大部分设置,以及少量可用于禁用迁移或关闭位置检查的附加属性。 如果您需要对配置进行更多控制,请考虑注册一个 FlywayConfigurationCustomizer bean。spring-doc.cadn.net.cn

Spring Boot 调用 Flyway.migrate() 以执行数据库迁移。 如果您希望有更多控制权,请提供一个实现 FlywayMigrationStrategy@Beanspring-doc.cadn.net.cn

Flyway 支持 SQL 和 Java 回调. 要使用基于 SQL 的回调,请将回调脚本放在 classpath:db/migration 目录中。 要使用基于 Java 的回调,请创建一个或多个实现 Callback 的 bean。 任何此类 bean 会自动注册到 Flyway。 可以通过使用 @Order 进行排序,或者通过实现 Orderedspring-doc.cadn.net.cn

默认情况下,Flyway 会自动装配上下文中的 (@Primary) DataSource 并将其用于迁移。 如果您希望使用不同的 DataSource,可以创建一个并将其 @Bean 标记为 @FlywayDataSource。 如果您这样做并且想要两个数据源(例如通过保留主要的自动配置 DataSource),请记住将 @Bean 注解的 defaultCandidate 属性设置为 false。 或者,您可以通过在外部属性中设置 spring.flyway.[url,user,password] 来使用 Flyway 原生的 DataSource。 设置 spring.flyway.urlspring.flyway.user 中的任意一个都足以使 Flyway 使用其自己的 DataSource。 如果这三个属性中的任何一个未设置,则将使用其等效的 spring.datasource 属性的值。spring-doc.cadn.net.cn

您还可以使用 Flyway 为特定场景提供数据。 例如,您可以将测试专用的迁移脚本放置在 src/test/resources 中,它们仅在您的应用程序以测试模式启动时运行。 此外,您可以使用基于配置文件的配置来自定义 spring.flyway.locations,以便某些迁移脚本仅在特定配置文件激活时运行。 例如,在 application-dev.properties 中,您可以指定以下设置:spring-doc.cadn.net.cn

spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
spring:
  flyway:
    locations: "classpath:/db/migration,classpath:/dev/db/migration"

通过该设置,dev/db/migration 中的迁移仅在 dev 配置文件处于活动状态时运行。spring-doc.cadn.net.cn

在启动时执行 Liquibase 数据库迁移

要在启动时自动运行 Liquibase 数据库迁移,请将 org.liquibase:liquibase-core 添加到您的类路径中。spring-doc.cadn.net.cn

当您将 org.liquibase:liquibase-core 添加到类路径时,数据库迁移默认会在应用程序启动期间和测试运行之前执行。 可以通过使用 spring.liquibase.enabled 属性,在 maintest 配置中设置不同的值来自定义此行为。 无法使用两种不同的方式来初始化数据库(例如,应用程序启动时使用 Liquibase,测试运行时使用 JPA)。spring-doc.cadn.net.cn

默认情况下,主变更日志从 db/changelog/db.changelog-master.yaml 读取,但你可以通过设置 spring.liquibase.change-log 来更改位置。 除了 YAML 之外,Liquibase 还支持 JSON、XML 和 SQL 变更日志格式。spring-doc.cadn.net.cn

默认情况下,Liquibase 会自动装配上下文中的 (@Primary) DataSource 并将其用于迁移。 如果您需要使用不同的 DataSource,可以创建一个并将其 @Bean 标记为 @LiquibaseDataSource。 如果您这样做并希望使用两个数据源(例如,通过保留主要的自动配置的 DataSource),请记住将 @Bean 注解的 defaultCandidate 属性设置为 false。 或者,您可以通过在外部属性中设置 spring.liquibase.[driver-class-name,url,user,password] 来使用 Liquibase 原生的 DataSource。 设置 spring.liquibase.urlspring.liquibase.user 中的任意一个都足以使 Liquibase 使用其自己的 DataSource。 如果这三个属性中的任何一个未设置,则将使用其等效的 spring.datasource 属性的值。spring-doc.cadn.net.cn

有关可用设置(如上下文、默认架构等)的详细信息,请参阅 LiquibasePropertiesspring-doc.cadn.net.cn

你也可以使用一个 Customizer<Liquibase> bean,如果你希望在它被使用之前自定义 Liquibase 实例的话。spring-doc.cadn.net.cn

使用 Flyway 进行仅测试的迁移

如果您想创建用于填充测试数据库的 Flyway 迁移脚本,请将它们放置在 src/test/resources/db/migration 中。 例如,名为 src/test/resources/db/migration/V9999__test-data.sql 的文件将在生产环境迁移之后执行,且仅在您运行测试时执行。 您可以使用此文件来创建所需的测试数据。 此文件不会被打包到您的 uber jar 或容器中。spring-doc.cadn.net.cn

使用 Liquibase 进行仅测试的迁移

如果您想创建用于填充测试数据库的Liquibase迁移,可以利用Liquibase上下文。 有关更多信息,请参阅相关的博客文章spring-doc.cadn.net.cn

实际上,这意味着向包含测试数据的变更集添加 context:@test 属性,例如:spring-doc.cadn.net.cn

--liquibase formatted sql

--changeset alice:1 context:@test
insert into project (id, name) values (1, 'Spring Boot');

并在您希望应用包含测试数据的变更集的环境中使用 spring.liquibase.contexts=testspring-doc.cadn.net.cn

依赖于已初始化的数据库

数据库初始化是在应用程序启动时作为应用上下文刷新的一部分执行的。 为了在启动期间访问已初始化的数据库,会自动检测充当数据库初始化器的 beans 以及需要数据库已初始化的 beans。 初始化依赖于数据库已初始化的 beans 会被配置为依赖于那些初始化数据库的 beans。 如果在启动过程中,你的应用程序尝试访问数据库但数据库尚未初始化,你可以配置额外的 beans 检测,这些 beans 用于初始化数据库并要求数据库已初始化。spring-doc.cadn.net.cn

检测数据库初始化器

Spring Boot 将自动检测以下类型的用于初始化 SQL 数据库的 Bean:spring-doc.cadn.net.cn

如果您使用的是用于数据库初始化库的第三方Starters,它可能会提供一个检测器,以便自动检测其他类型的bean。 要检测其他bean,请在META-INF/spring.factories中注册DatabaseInitializerDetector的实现。spring-doc.cadn.net.cn

检测依赖于数据库初始化的 Bean

Spring Boot 将自动检测依赖于数据库初始化的以下类型的 Bean:spring-doc.cadn.net.cn

如果您使用的是第三方启动数据访问库,它可能会提供一个检测器,以便自动检测其他类型的bean。 要检测其他bean,请在META-INF/spring.factories中注册DependsOnDatabaseInitializationDetector的实现。 或者,将@DependsOnDatabaseInitialization注解到bean的类或其@Bean方法上。spring-doc.cadn.net.cn