75. 数据库初始化

一个数据库可以使用不同的方式进行初始化,这取决于你的技术栈。或者你可以手动完成该任务,只要数据库是单独的过程。

75.1 使用JPA初始化数据库

JPA有个生成DDL的特性,并且可以设置为在数据库启动时运行,这可以通过两个外部属性进行控制:

  • spring.jpa.generate-ddlboolean)控制该特性的关闭和开启,跟实现者没关系。
  • spring.jpa.hibernate.ddl-autoenum)是一个Hibernate特性,用于更细力度的控制该行为,更多详情参考以下内容。

75.2 使用Hibernate初始化数据库

你可以显式设置spring.jpa.hibernate.ddl-auto,标准的Hibernate属性值有nonevalidateupdatecreatecreate-drop。Spring Boot根据你的数据库是否为内嵌数据库来选择相应的默认值,如果是内嵌型的则默认值为create-drop,否则为none。通过查看Connection类型可以检查是否为内嵌型数据库,hsqldb,h2和derby是内嵌的,其他都不是。当从内存数据库迁移到一个真正的数据库时,你需要当心,在新的平台中不能对数据库表和数据是否存在进行臆断,你也需要显式设置ddl-auto,或使用其他机制初始化数据库。

此外,启动时处于classpath根目录下的import.sql文件会被执行。这在demos或测试时很有用,但在生产环境中你可能不期望这样。这是Hibernate的特性,和Spring没有一点关系。

75.3 使用Spring JDBC初始化数据库

Spring JDBC有一个初始化DataSource特性,Spring Boot默认启用该特性,并从标准的位置schema.sqldata.sql(位于classpath根目录)加载SQL。此外,Spring Boot将加载schema-${platform}.sqldata-${platform}.sql文件(如果存在),在这里platformspring.datasource.platform的值,比如,你可以将它设置为数据库的供应商名称(hsqldb, h2, oracle, mysql, postgresql等)。Spring Boot默认启用Spring JDBC初始化快速失败特性,所以如果脚本导致异常产生,那应用程序将启动失败。脚本的位置可以通过设置spring.datasource.schemaspring.datasource.data来改变,如果设置spring.datasource.initialize=false则哪个位置都不会被处理。

你可以设置spring.datasource.continue-on-error=true禁用快速失败特性。一旦应用程序成熟并被部署了很多次,那该设置就很有用,因为脚本可以充当"可怜人的迁移"-例如,插入失败时意味着数据已经存在,也就没必要阻止应用继续运行。

如果你想要在一个JPA应用中使用schema.sql,那如果Hibernate试图创建相同的表,ddl-auto=create-drop将导致错误产生。为了避免那些错误,可以将ddl-auto设置为“”(推荐)或none。不管是否使用ddl-auto=create-drop,你总可以使用data.sql初始化新数据。

75.4 初始化Spring Batch数据库

如果你正在使用Spring Batch,那么它会为大多数的流行数据库平台预装SQL初始化脚本。Spring Boot会检测你的数据库类型,并默认执行那些脚本,在这种情况下将关闭快速失败特性(错误被记录但不会阻止应用启动)。这是因为那些脚本是可信任的,通常不会包含bugs,所以错误会被忽略掉,并且对错误的忽略可以让脚本具有幂等性。你可以使用spring.batch.initializer.enabled=false显式关闭初始化功能。

75.5 使用高级数据迁移工具

Spring Boot支持两种高级数据迁移工具Flyway(基于SQL)和Liquibase(XML)。

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

想要在启动时自动运行Flyway数据库迁移,需要将org.flywaydb:flyway-core添加到你的classpath下。

迁移是一些V<VERSION>__<NAME>.sql格式的脚本(<VERSION>是一个下划线分割的版本号,比如'1'或'2_1')。默认情况下,它们存放在classpath:db/migration文件夹中,但你可以使用flyway.locations(一个列表)改变它。详情可参考flyway-core中的Flyway类,查看一些可用的配置,比如schemas。Spring Boot在FlywayProperties中提供了一个小的属性集,可用于禁止迁移,或关闭位置检测。Spring Boot将调用Flyway.migrate()执行数据库迁移,如果想要更多控制可提供一个实现FlywayMigrationStrategy@Bean

默认情况下,Flyway将自动注入(@PrimaryDataSource到你的上下文,并用它进行数据迁移。如果想使用不同的DataSource,你可以创建一个,并将它标记为@FlywayDataSource@Bean-如果你这样做了,且想要两个数据源,记得创建另一个并将它标记为@Primary,或者你可以通过在外部配置文件中设置flyway.[url,user,password]来使用Flyway的原生DataSource

这是一个Flyway示例,你可以作为参考。

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

想要在启动时自动运行Liquibase数据库迁移,你需要将org.liquibase:liquibase-core添加到classpath下。

你可以使用liquibase.change-log设置master变化日志位置,默认从db/changelog/db.changelog-master.yaml读取。除了YAML,Liquibase还支持JSON, XML和SQL改变日志格式。查看LiquibaseProperties获取可用配置,比如上下文,默认schema等。

这里有个Liquibase示例可作为参考。