85. Database Initialization

可以使用不同的方式初始化 SQL 数据库,具体取决于堆栈是什么。当然,如果数据库是一个单独的过程,您也可以手动执行。

85.1 使用 JPA 初始化数据库

JPA 具有用于 DDL 生成的功能,可以将其设置为在启动时针对数据库运行。这是通过两个外部属性控制的:

  • spring.jpa.generate-ddl(布尔值)打开和关闭该功能,并且与供应商无关。

  • spring.jpa.hibernate.ddl-auto(枚举)是一种 Hibernate 功能,可以更精细地控制行为。此功能将在本指南的后面部分详细介绍。

85.2 使用 Hibernate 初始化数据库

您可以显式设置spring.jpa.hibernate.ddl-auto,并且标准的 Hibernate 属性值为nonevalidateupdatecreatecreate-drop。 Spring Boot 根据是否认为您的数据库已嵌入为您选择默认值。如果未检测到任何模式 Management 器,则默认为create-drop,否则为none。通过查看Connection类型,可以检测到嵌入式数据库。嵌入了hsqldbh2derby,其他未嵌入。从内存数据库转换为“实际”数据库时,请不要对新平台中表和数据的存在做出假设。您必须显式设置ddl-auto或使用其他机制之一来初始化数据库。

Note

您可以通过启用org.hibernate.SQLLogger 来输出架构创建。如果启用debug mode,则会自动为您完成此操作。

另外,如果 Hibernate 从头开始创建架构(即ddl-auto属性设置为createcreate-drop),则在启动时将在 Classpath 的根目录中执行名为import.sql的文件。如果您小心的话,这对于演示和测试很有用,但是您可能不想在生产环境的 Classpath 中使用它。这是一个 Hibernate 功能(与 Spring 无关)。

85.3 初始化数据库

Spring Boot 可以自动创建DataSource的架构(DDL 脚本)并对其进行初始化(DML 脚本)。它从标准根 Classpath 位置:schema.sqldata.sql加载 SQL。另外,Spring Boot 处理schema-${platform}.sqldata-${platform}.sql文件(如果存在),其中platformspring.datasource.platform的值。这使您可以在必要时切换到特定于数据库的脚本。例如,您可以选择将其设置为数据库的供应商名称(hsqldbh2oraclemysqlpostgresql等)。

Note

Spring Boot 自动创建嵌入式DataSource的架构。可以使用spring.datasource.initialization-mode属性来自定义此行为。例如,如果要始终初始化DataSource而不考虑其类型:

spring.datasource.initialization-mode=always

默认情况下,Spring Boot 启用 Spring JDBC 初始化程序的快速失败功能。这意味着,如果脚本导致异常,则应用程序将无法启动。您可以通过设置spring.datasource.continue-on-error来调整行为。

Note

在基于 JPA 的应用程序中,您可以选择让 Hibernate 创建架构或使用schema.sql,但是您不能两者都做。如果使用schema.sql,请确保禁用spring.jpa.hibernate.ddl-auto

85.4 初始化 Spring Batch 数据库

如果您使用 Spring Batch,则它随大多数流行的数据库平台一起预包装了 SQL 初始化脚本。 Spring Boot 可以检测数据库类型并在启动时执行这些脚本。如果您使用嵌入式数据库,则默认情况下会发生这种情况。您还可以为任何数据库类型启用它,如以下示例所示:

spring.batch.initialize-schema=always

您还可以通过设置spring.batch.initialize-schema=never显式关闭初始化。

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

Spring Boot 支持两个更高级别的迁移工具:FlywayLiquibase

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

要在启动时自动运行 Flyway 数据库迁移,请将org.flywaydb:flyway-core添加到您的 Classpath 中。

迁移是格式为V<VERSION>__<NAME>.sql(带有<VERSION>下划线分隔的版本,例如“ 1”或“ 2_1”)的脚本。默认情况下,它们位于名为classpath:db/migration的文件夹中,但是您可以通过设置spring.flyway.locations来修改该位置。这是一个或多个classpath:filesystem:位置的逗号分隔列表。例如,以下配置将在默认 Classpath 位置和/opt/migration目录中搜索脚本:

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

您还可以添加特殊的{vendor}占位符以使用特定于供应商的脚本。假设以下内容:

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

前面的配置没有使用db/migration,而是根据数据库的类型(例如db/migration/mysql表示 MySQL)来设置要使用的文件夹。 DatabaseDriver中提供了受支持的数据库列表。

FlywayProperties提供了 Flyway 的大多数设置以及少量的其他属性,可用于禁用迁移或关闭位置检查。如果需要对配置进行更多控制,请考虑注册FlywayConfigurationCustomizer bean。

Spring Boot 调用Flyway.migrate()来执行数据库迁移。如果您想要更多控制权,请提供实现FlywayMigrationStrategy@Bean

Flyway 支持 SQL 和 Java callbacks。要使用基于 SQL 的回调,请将回调脚本放在classpath:db/migration文件夹中。要使用基于 Java 的回调,请创建一个或多个实现Callback的 bean。任何此类 bean 都会自动通过Flyway注册。可以使用@Order或实现Ordered对其进行排序。也可以检测到实现不推荐使用的FlywayCallback接口的 Bean,但是不能与Callback Bean 一起使用。

默认情况下,Flyway 自动在您的上下文中自动连接(@Primary)DataSource并将其用于迁移。如果您想使用其他DataSource,则可以创建一个并将其@Bean标记为@FlywayDataSource。如果这样做并想要两个数据源,请记住创建另一个数据源并将其标记为@Primary。另外,您可以通过在外部属性中设置spring.flyway.[url,user,password]来使用 Flyway 的本机DataSource。设置spring.flyway.urlspring.flyway.user足以使 Flyway 使用其自己的DataSource。如果未设置这三个属性中的任何一个,则将使用其等效的spring.datasource属性的值。

有一个Flyway sample,以便您可以了解如何进行设置。

您还可以使用 Flyway 为特定情况提供数据。例如,您可以将特定于测试的迁移放在src/test/resources中,并且仅在您的应用程序开始进行测试时才运行它们。另外,您可以使用特定于配置文件的配置来自定义spring.flyway.locations,以便仅在特定配置文件处于 Active 状态时才运行某些迁移。例如,在application-dev.properties中,您可以指定以下设置:

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

使用该设置,只有在dev配置文件处于 Active 状态时,才能在dev/db/migration中进行迁移。

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

要在启动时自动运行 Liquibase 数据库迁移,请将org.liquibase:liquibase-core添加到您的 Classpath 中。

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

默认情况下,Liquibase 在您的上下文中自动装配(@Primary)DataSource并将其用于迁移。如果需要使用其他DataSource,则可以创建一个@Bean并将其标记为@LiquibaseDataSource。如果这样做,并且想要两个数据源,请记住创建另一个数据源并将其标记为@Primary。另外,您可以通过在外部属性中设置spring.liquibase.[url,user,password]来使用 Liquibase 的本机DataSource。设置spring.liquibase.urlspring.liquibase.user足以使 Liquibase 使用其自己的DataSource。如果未设置这三个属性中的任何一个,则将使用其等效的spring.datasource属性的值。

有关可用设置(例如上下文,默认架构等)的详细信息,请参见LiquibaseProperties

有一个Liquibase sample,以便您可以了解如何进行设置。