SQL 数据库可以通过不同的方式初始化,具体取决于您的堆栈是什么。 当然,您也可以手动执行此操作,前提是数据库是一个单独的进程。 建议使用单一机制进行架构生成。
使用 Hibernate 初始化数据库
您可以设置为控制 Hibernate 的数据库初始化。
支持的值为 、 、 、 和 。
Spring Boot 会根据您是否使用嵌入式数据库来选择默认值。
通过查看类型和 JDBC URL 来识别嵌入式数据库。、 或 是嵌入式数据库,而其他则不是。
如果识别了嵌入式数据库,但未检测到模式管理器(Flyway 或 Liquibase),则默认为 。
在所有其他情况下,它默认为 。spring.jpa.hibernate.ddl-auto
none
validate
update
create
create-drop
Connection
hsqldb
h2
derby
ddl-auto
create-drop
none
从内存中数据库切换到“真实”数据库时要小心,不要假设新平台中是否存在表和数据。
您必须显式设置或使用其他机制之一来初始化数据库。ddl-auto
您可以通过启用记录器来输出架构创建。
如果启用调试模式,则会自动为您完成此操作。org.hibernate.SQL |
此外,如果 Hibernate 从头开始创建架构(即,如果属性设置为 或),则在启动时执行在类路径根目录中命名的文件。
如果您小心的话,这对于演示和测试很有用,但可能不是您希望在生产环境中的类路径上出现的东西。
这是 Hibernate 的功能(与 Spring 无关)。import.sql
ddl-auto
create
create-drop
您可以通过启用记录器来输出架构创建。
如果启用调试模式,则会自动为您完成此操作。org.hibernate.SQL |
使用基本 SQL 脚本初始化数据库
Spring Boot 可以自动创建 JDBC 或 R2DBC 的架构(DDL 脚本)并初始化其数据(DML 脚本)。DataSource
ConnectionFactory
默认情况下,它从 加载架构脚本,从 加载数据脚本。
这些架构和数据脚本的位置可以分别使用 和 进行自定义。
前缀表示即使文件不存在,应用程序也会启动。
若要使应用程序在文件不存在时无法启动,请删除前缀。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 Boot 启用其基于脚本的数据库初始值设定项的快速故障功能。
这意味着,如果脚本导致异常,应用程序将无法启动。
您可以通过设置 来调整该行为。spring.sql.init.mode
always
spring.sql.init.mode
never
spring.sql.init.continue-on-error
缺省情况下,在创建任何 JPA Bean 之前执行基于脚本的初始化。 可用于为 JPA 管理的实体创建模式,并可用于填充它。
虽然我们不建议使用多个数据源初始化技术,但如果您希望基于脚本的初始化能够基于 Hibernate 执行的架构创建进行构建,请设置为 。
这会将数据源初始化推迟到创建并初始化任何 Bean 之后。 然后可用于对 Hibernate 执行的任何架构创建进行添加,并可用于填充它。DataSource
EntityManagerFactory
schema.sql
data.sql
DataSource
spring.jpa.defer-datasource-initialization
true
EntityManagerFactory
schema.sql
data.sql
初始化脚本支持单行注释和块注释。
不支持其他注释格式。-- /* */ |
如果您使用的是更高级别的数据库迁移工具,如 Flyway 或 Liquibase,则应单独使用它们来创建和初始化架构。
不建议将 basic 和 scripts 与 Flyway 或 Liquibase 一起使用,并且将在将来的版本中删除支持。schema.sql
data.sql
初始化脚本支持单行注释和块注释。
不支持其他注释格式。-- /* */ |
初始化 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 数据库迁移,请将 添加到类路径中。org.flywaydb:flyway-core
通常,迁移是以下形式的脚本(具有下划线分隔的版本,例如“1”或“2_1”)。
默认情况下,它们位于名为 的目录中,但您可以通过设置 来修改该位置。
这是一个或多个位置的逗号分隔列表。
例如,以下配置将在默认类路径位置和目录中搜索脚本:V<VERSION>__<NAME>.sql
<VERSION>
classpath:db/migration
spring.flyway.locations
classpath:
filesystem:
/opt/migration
-
Properties
-
YAML
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
spring:
flyway:
locations: "classpath:db/migration,filesystem:/opt/migration"
您还可以添加一个特殊的占位符来使用特定于供应商的脚本。
假设如下:{vendor}
-
Properties
-
YAML
spring.flyway.locations=classpath:db/migration/{vendor}
spring:
flyway:
locations: "classpath:db/migration/{vendor}"
前面的配置不是使用 ,而是根据数据库的类型(例如 MySQL)设置要使用的目录。
DatabaseDriver
中提供了受支持的数据库列表。db/migration
db/migration/mysql
迁移也可以用 Java 编写。
Flyway 将自动配置任何实现 的 Bean。JavaMigration
FlywayProperties
提供了 Flyway 的大部分设置和一小部分附加属性,可用于禁用迁移或关闭位置检查。
如果您需要对配置进行更多控制,请考虑注册 Bean。FlywayConfigurationCustomizer
Spring Boot 调用以执行数据库迁移。
如果需要更多控制,请提供实现 FlywayMigrationStrategy
的 。Flyway.migrate()
@Bean
Flyway 支持 SQL 和 Java 回调。
若要使用基于 SQL 的回调,请将回调脚本放在目录中。
要使用基于 Java 的回调,请创建一个或多个实现 的 Bean 。
任何此类 Bean 都会自动注册到 。
它们可以通过使用或实现来订购。
也可以检测到实现已弃用接口的 Bean,但它们不能与 Bean 一起使用。classpath:db/migration
Callback
Flyway
@Order
Ordered
FlywayCallback
Callback
默认情况下,Flyway 会在您的上下文中自动连接 (),并将其用于迁移。
如果你想使用不同的 ,你可以创建一个并将其标记为 。
如果这样做并且需要两个数据源,请记住创建另一个数据源并将其标记为 。
或者,您可以通过设置外部属性来使用 Flyway 的本机。
设置 or 足以使 Flyway 使用自己的 .
如果尚未设置这三个属性中的任何一个,则将使用其等效属性的值。@Primary
DataSource
DataSource
@Bean
@FlywayDataSource
@Primary
DataSource
spring.flyway.[url,user,password]
spring.flyway.url
spring.flyway.user
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
将 添加到类路径时,数据库迁移默认在应用程序启动期间和测试运行之前运行。
可以使用属性自定义此行为,并在 和 配置中设置不同的值。
不能使用两种不同的方法来初始化数据库(例如,用于应用程序启动的 Liquibase,用于测试运行的 JPA)。 |
默认情况下,主更改日志是从 读取的,但您可以通过设置 来更改位置。
除了 YAML,Liquibase 还支持 JSON、XML 和 SQL 更改日志格式。db/changelog/db.changelog-master.yaml
spring.liquibase.change-log
默认情况下,Liquibase 会在您的上下文中自动连接 (),并将其用于迁移。
如果您需要使用不同的 ,您可以创建一个并将其标记为 。
如果这样做并且需要两个数据源,请记住创建另一个数据源并将其标记为 。
或者,您可以通过设置外部属性来使用 Liquibase 的原生属性。
设置 or 足以使 Liquibase 使用自己的 .
如果尚未设置这三个属性中的任何一个,则将使用其等效属性的值。@Primary
DataSource
DataSource
@Bean
@LiquibaseDataSource
@Primary
DataSource
spring.liquibase.[driver-class-name,url,user,password]
spring.liquibase.url
spring.liquibase.user
DataSource
spring.datasource
有关可用设置(如上下文、默认架构等)的详细信息,请参阅 LiquibaseProperties
。
使用 Flyway 进行仅限测试的迁移
如果要创建填充测试数据库的 Flyway 迁移,请将它们放在 .
例如,只有在运行测试时,才会执行名为 file 的文件。
您可以使用此文件创建所需的测试数据。
此文件不会打包在您的 uber jar 或容器中。src/test/resources/db/migration
src/test/resources/db/migration/V9999__test-data.sql
使用 Liquibase 进行仅测试迁移
如果要创建填充测试数据库的 Liquibase 迁移,则必须创建一个测试更改日志,其中还包括生产更改日志。
首先,您需要将 Liquibase 配置为在运行测试时使用不同的更改日志。
一种方法是创建一个 Spring Boot 配置文件并将 Liquibase 属性放入其中。
为此,请创建一个名为并将以下属性放入其中的文件:test
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 或容器中。
它包括生产变更日志,然后声明一个新的变更集,其设置指定它在运行所有生产变更集后运行。
例如,现在可以使用插入变更集来插入数据,或者使用 sql 变更集直接执行 SQL。runOrder: last
最后要做的是将 Spring Boot 配置为在运行测试时激活配置文件。
为此,您可以将注释添加到带注释的测试类中。test
@ActiveProfiles("test")
@SpringBootTest
将 添加到类路径时,数据库迁移默认在应用程序启动期间和测试运行之前运行。
可以使用属性自定义此行为,并在 和 配置中设置不同的值。
不能使用两种不同的方法来初始化数据库(例如,用于应用程序启动的 Liquibase,用于测试运行的 JPA)。 |
依赖于初始化的数据库
数据库初始化是在应用程序启动时作为应用程序上下文刷新的一部分执行的。 为了允许在启动期间访问已初始化的数据库,将自动检测充当数据库初始值设定项的 Bean 和需要初始化该数据库的 Bean。 其初始化依赖于已初始化的数据库的 Bean 被配置为依赖于初始化它的 Bean。 如果在启动过程中,应用程序尝试访问数据库,但尚未初始化该数据库,那么可以配置初始化数据库并要求已初始化的 Bean 的附加检测。
检测数据库初始值设定项
Spring Boot 将自动检测初始化 SQL 数据库的以下类型的 Bean:
-
DataSourceScriptDatabaseInitializer
-
EntityManagerFactory
-
Flyway
-
FlywayMigrationInitializer
-
R2dbcScriptDatabaseInitializer
-
SpringLiquibase
如果对数据库初始化库使用第三方启动器,它可能会提供检测器,以便自动检测其他类型的 Bean。
要检测其他 Bean,请注册 in 的实现。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
) -
JdbcClient
-
JdbcOperations
-
NamedParameterJdbcOperations
如果您使用的是第三方起始数据访问库,它可能会提供一个检测器,以便自动检测其他类型的 Bean。
要检测其他 Bean,请注册 in 的实现。
或者,用 .DependsOnDatabaseInitializationDetector
META-INF/spring.factories
@Bean
@DependsOnDatabaseInitialization