78. Database initialization

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

78.1 使用 JPA 初始化数据库

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

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

  • spring.jpa.hibernate.ddl-auto(枚举)是一种 Hibernate 功能,可以更精细地控制行为。有关更多详细信息,请参见下文。

78.2 使用 Hibernate 初始化数据库

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

Note

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

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

78.3 初始化数据库

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

Spring Boot 默认情况下启用 Spring JDBC 初始化程序的快速失败功能,因此,如果脚本导致异常,则应用程序将无法启动。您可以使用spring.datasource.continue-on-error进行调整。

Note

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

您还可以通过将spring.datasource.initialize设置为false来禁用初始化。

78.4 初始化 Spring Batch 数据库

如果您使用的是 Spring Batch,则它预包装了针对大多数流行数据库平台的 SQL 初始化脚本。 Spring Boot 将检测您的数据库类型,并默认执行这些脚本,在这种情况下,会将快速失败设置切换为 false(记录了错误,但不会阻止应用程序启动)。这是因为已知脚本是可靠的,并且通常不包含错误,因此错误是可以忽略的,而忽略它们会使脚本成为幂等。您可以使用spring.batch.initializer.enabled=false明确关闭初始化。

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

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

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

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

迁移是格式为V<VERSION>__<NAME>.sql(带有<VERSION>下划线分隔的版本,例如“ 1”或“ 2_1”)的脚本。默认情况下,它们位于classpath:db/migration文件夹中,但是您可以使用flyway.locations对其进行修改。您还可以添加特殊的{vendor}占位符以使用特定于供应商的脚本。假设以下内容:

flyway.locations=db/migration/{vendor}

而不是使用db/migration,此配置将根据数据库的类型(即db/migration/mysql用于 MySQL)来设置要使用的文件夹。 DatabaseDriver中提供了受支持的数据库列表。

另请参见 flyway-core 的 Flyway 类,以获取可用设置(例如模式等)的详细信息。此外,Spring Boot 在FlywayProperties中提供了一小套属性,可用于禁用迁移或关闭位置检查。 Spring Boot 将调用Flyway.migrate()来执行数据库迁移。如果您想要更多控制权,请提供实现FlywayMigrationStrategy@Bean

Tip

如果要使用Flyway callbacks,这些脚本也应位于classpath:db/migration文件夹中。

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

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

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

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

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

默认情况下,从db/changelog/db.changelog-master.yaml读取主更改日志,但可以使用liquibase.change-log进行设置。除了 YAML,Liquibase 还支持 JSON,XML 和 SQL 更改日志格式。

默认情况下,Liquibase 将在您的上下文中自动连接(@Primary)DataSource并将其用于迁移。如果您想使用其他DataSource,则可以创建一个DataSource并将其@Bean标记为@LiquibaseDataSource-如果您这样做,则记住要创建另一个DataSource并将其标记为@Primary(如果要使用两个数据源)。或者,您可以通过在外部属性中设置liquibase.[url,user,password]来使用 Liquibase 的本机DataSource

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

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