数据库初始化
SQL 数据库可以以不同的方式初始化,具体取决于您的堆栈是什么。 当然,您也可以手动执行此作,前提是数据库是一个单独的过程。 建议使用单个机制来生成架构。
使用 Hibernate 初始化数据库
您可以设置spring.jpa.hibernate.ddl-auto来控制 Hibernate 的数据库初始化。
支持的值包括none,validate,update,create和create-drop.
Spring Boot 根据您是否使用嵌入式数据库为您选择默认值。
嵌入式数据库是通过查看Connectiontype 和 JDBC url 的 URL 进行验证。hsqldb,h2或derby是嵌入式数据库,而其他数据库则不是。
如果识别出嵌入式数据库,但未检测到架构管理器(Flyway 或 Liquibase),则ddl-auto默认为create-drop.
在所有其他情况下,它默认为none.
从内存中切换到“真实”数据库时要小心,不要对新平台中存在表和数据做出假设。
您必须将ddl-auto显式或使用其他机制之一来初始化数据库。
您可以通过启用org.hibernate.SQL记录。
如果您启用 debug 模式,则会自动为您完成此作。 |
此外,名为import.sql如果 Hibernate 从头开始创建模式(即,如果ddl-auto属性设置为create或create-drop).
如果您小心,这对于演示和测试很有用,但可能不是您希望在 production 中的 Classpath 上的内容。
它是一个 Hibernate 功能(与 Spring 无关)。
使用基本 SQL 脚本初始化数据库
Spring Boot 可以自动创建 JDBC 的模式(DDL 脚本)DataSource或 R2DBCConnectionFactory并初始化其数据(DML 脚本)。
默认情况下,它从optional:classpath*:schema.sql和数据脚本optional:classpath*:data.sql.
这些架构和数据脚本的位置可以使用spring.sql.init.schema-locations和spring.sql.init.data-locations分别。
这optional:前缀表示即使文件不存在,应用程序也会启动。
要使应用程序在文件不存在时无法启动,请删除optional:前缀。
此外,Spring Boot 会处理optional:classpath*:schema-${platform}.sql和optional:classpath*:data-${platform}.sql文件(如果存在),其中${platform}的值是spring.sql.init.platform.
这允许您在必要时切换到特定于数据库的脚本。
例如,您可以选择将其设置为数据库的提供商名称 (hsqldb,h2,oracle,mysql,postgresql等)。
默认情况下,仅在使用嵌入式内存数据库时执行 SQL 数据库初始化。
要始终初始化 SQL 数据库,而不管其类型如何,请将spring.sql.init.mode自always.
同样,要禁用初始化,请将spring.sql.init.mode自never.
默认情况下, Spring Boot 启用其基于脚本的数据库初始化器的快速失败功能。
这意味着,如果脚本导致异常,应用程序将无法启动。
您可以通过设置spring.sql.init.continue-on-error.
基于脚本DataSource默认情况下,在任何 JPA 之前执行初始化EntityManagerFactorybean 被创建。schema.sql可用于为 JPA 托管的实体创建架构,并且data.sql可用于填充它。
虽然我们不建议使用多个数据源初始化技术,但如果您希望使用基于脚本的DataSource初始化,以便能够在 Hibernate 执行的架构创建的基础上进行构建,请将spring.jpa.defer-datasource-initialization自true.
这会将数据源初始化推迟到任何EntityManagerFactorybean 已创建并初始化。schema.sql然后,可以用于对 Hibernate 执行的任何模式创建进行添加,并且data.sql可用于填充它。
初始化脚本支持单行注释和块注释。
不支持其他注释格式。--/* */ |
如果您使用的是更高级别的数据库迁移工具,如 Flyway 或 Liquibase,则应单独使用它们来创建和初始化架构。
使用基本schema.sql和data.sql不建议将脚本与 Flyway 或 Liquibase 一起使用,并且在未来版本中将删除支持。
初始化 Spring Batch 数据库
如果您使用 Spring Batch,则它预打包了适用于大多数流行数据库平台的 SQL 初始化脚本。 Spring Boot 可以检测您的数据库类型并在启动时执行这些脚本。 如果您使用嵌入式数据库,则默认情况下会发生这种情况。 您还可以为任何数据库类型启用它,如以下示例所示:
-
Properties
-
YAML
spring.batch.jdbc.initialize-schema=always
spring:
batch:
jdbc:
initialize-schema: "always"
您还可以通过设置spring.batch.jdbc.initialize-schema自never.
使用更高级别的数据库迁移工具
启动时执行 Flyway 数据库迁移
要在启动时自动运行 Flyway 数据库迁移,请将适当的 Flyway 模块添加到您的 Classpath 中。
内存中数据库和基于文件的数据库由org.flywaydb:flyway-core.
否则,需要特定于数据库的模块。
例如,使用org.flywaydb:flyway-database-postgresql与 PostgreSQL 和org.flywaydb:flyway-mysql使用 MySQL。
有关更多详细信息,请参阅 Flyway 文档。
通常,迁移是格式为V<VERSION>__<NAME>.sql(使用<VERSION>下划线分隔的版本,例如 '1' 或 '2_1')。
默认情况下,它们位于名为classpath:db/migration,但您可以通过设置spring.flyway.locations.
这是一个或多个classpath:或filesystem:地点。
例如,以下配置将在默认 classpath 位置和/opt/migration目录:
-
Properties
-
YAML
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
spring:
flyway:
locations: "classpath:db/migration,filesystem:/opt/migration"
您还可以添加特殊的{vendor}placeholder 以使用特定于提供商的脚本。
假设以下内容:
-
Properties
-
YAML
spring.flyway.locations=classpath:db/migration/{vendor}
spring:
flyway:
locations: "classpath:db/migration/{vendor}"
而不是使用db/migration中,前面的配置会根据数据库的类型(例如db/migration/mysql用于 MySQL)。
支持的数据库列表位于DatabaseDriver.
迁移也可以用 Java 编写。
Flyway 将自动配置任何实现JavaMigration.
FlywayProperties提供了 Flyway 的大部分设置和一小部分附加属性,这些属性可用于禁用迁移或关闭位置检查。
如果您需要对配置进行更多控制,请考虑注册FlywayConfigurationCustomizer豆。
Spring Boot 调用Flyway.migrate()以执行数据库迁移。
如果您想要更多控制权,请提供@Bean实现FlywayMigrationStrategy.
Flyway 支持 SQL 和 Java 回调。
要使用基于 SQL 的回调,请将回调脚本放在classpath:db/migration目录。
要使用基于 Java 的回调,请创建一个或多个实现Callback.
任何此类 bean 都会自动注册到Flyway.
可以使用@Order或通过实施Ordered.
默认情况下,Flyway 会自动将 (@Primary) DataSource并将其用于迁移。
如果您想使用不同的DataSource,您可以创建一个 ID 并标记其@Bean如@FlywayDataSource.
如果您这样做并且需要两个数据源(例如,通过保留主自动配置的DataSource),请记得设置defaultCandidate属性的@Beanannotation 添加到false.
或者,您可以使用 Flyway 的原生DataSource通过设置spring.flyway.[url,user,password]在外部属性中。
设置spring.flyway.url或spring.flyway.user足以导致 Flyway 使用自己的DataSource.
如果尚未设置这三个属性中的任何一个,则其等效项的值spring.datasource属性。
您还可以使用 Flyway 为特定场景提供数据。
例如,您可以将特定于测试的迁移置于src/test/resources并且它们仅在应用程序启动进行测试时运行。
此外,您还可以使用特定于配置文件的配置来自定义spring.flyway.locations,以便某些迁移仅在特定配置文件处于活动状态时运行。
例如,在application-dev.properties,您可以指定以下设置:
-
Properties
-
YAML
spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
spring:
flyway:
locations: "classpath:/db/migration,classpath:/dev/db/migration"
通过该设置,迁移dev/db/migration仅在dev配置文件处于活动状态。
启动时执行 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,您可以创建一个 ID 并标记其@Bean如@LiquibaseDataSource.
如果您这样做并且需要两个数据源(例如,通过保留主自动配置的DataSource),请记得设置defaultCandidate属性的@Beanannotation 添加到false.
或者,您可以使用 Liquibase 的原生DataSource通过设置spring.liquibase.[driver-class-name,url,user,password]在外部属性中。
设置spring.liquibase.url或spring.liquibase.user足以使 Liquibase 使用自己的DataSource.
如果尚未设置这三个属性中的任何一个,则其等效项的值spring.datasource属性。
看LiquibaseProperties了解有关可用设置(如上下文、默认架构等)的详细信息。
您还可以使用Customizer<Liquibase>bean 如果要自定义Liquibase实例。
使用 Flyway 进行仅测试迁移
如果要创建填充测试数据库的 Flyway 迁移,请将它们放在src/test/resources/db/migration.
例如,名为src/test/resources/db/migration/V9999__test-data.sql将在您的生产迁移之后执行,并且仅在您运行测试时执行。
您可以使用此文件创建所需的测试数据。
此文件不会打包到您的 uber jar 或容器中。
使用 Liquibase 进行仅测试迁移
如果要创建填充测试数据库的 Liquibase 迁移,则必须创建一个测试更改日志,其中还包括生产更改日志。
首先,您需要将 Liquibase 配置为在运行测试时使用不同的更改日志。
一种方法是创建 Spring Boottestprofile 并将 Liquibase 属性放入其中。
为此,请创建一个名为src/test/resources/application-test.properties并将以下属性放入其中:
-
Properties
-
YAML
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-test.yaml
spring:
liquibase:
change-log: "classpath:/db/changelog/db.changelog-test.yaml"
这会将 Liquibase 配置为在test轮廓。
现在在src/test/resources/db/changelog/db.changelog-test.yaml:
databaseChangeLog:
- include:
file: classpath:/db/changelog/db.changelog-master.yaml
- changeSet:
runOrder: "last"
id: "test"
changes:
# Insert your changes here
此更改日志将在运行测试时使用,并且不会打包在您的 uber jar 或容器中。
它包括生产变更日志,然后声明一个新的变更集,其runOrder: lastsetting 指定它在运行所有 production 变更集之后运行。
例如,您现在可以使用 insert 变更集来插入数据,或者使用 sql 变更集直接执行 SQL。
最后要做的是配置 Spring Boot 以激活test配置文件。
为此,您可以添加@ActiveProfiles("test")注解添加到您的@SpringBootTest带注释的测试类。
依赖于初始化的数据库
数据库初始化是在应用程序启动时作为应用程序上下文刷新的一部分执行的。 为了允许在启动期间访问已初始化的数据库,将自动检测充当数据库初始值设定项的 bean 和需要初始化该数据库的 bean。 其初始化依赖于已初始化数据库的 Bean 被配置为依赖于初始化它的 Bean。 如果在启动期间,应用程序尝试访问数据库,但尚未初始化数据库,则可以配置对 bean 的其他检测,这些 bean 初始化数据库并要求已初始化数据库。
检测数据库初始值设定项
Spring Boot 将自动检测初始化 SQL 数据库的以下类型的 bean:
如果你将第三方Starters用于数据库初始化库,它可能会提供一个检测器,以便也自动检测其他类型的 bean。
要检测其他 bean,请注册DatabaseInitializerDetector在META-INF/spring.factories.
检测依赖于数据库初始化的 Bean
Spring Boot 将自动检测依赖于数据库初始化的以下类型的 bean:
-
AbstractEntityManagerFactoryBean(除非spring.jpa.defer-datasource-initialization设置为true) -
DSLContext(jOOQ) -
EntityManagerFactory(除非spring.jpa.defer-datasource-initialization设置为true)
如果您使用的是第三方入门数据访问库,则它可能会提供一个检测器,以便也会自动检测其他类型的 bean。
要检测其他 bean,请注册DependsOnDatabaseInitializationDetector在META-INF/spring.factories.
或者,对 Bean 的类或其@Beanmethod 替换为@DependsOnDatabaseInitialization.