說明
這一段時間項目變更比較大,經常修改表結構,然后各個環境數據庫均為修改,一不小心就忘掉了,等出問題才發現表結構沒有更新;遂尋找數據庫版本控制工具;最終確定為flyway
。
flyway說明
官網地址: https://flywaydb.org
按照官網的說明:
Version control for your database. Robust schema evolution across all your environments.With ease, pleasure and plain SQL.
官網原理圖: https://flywaydb.org/getstarted/how
腳本文件名定義
$PREFIX$VERSION__$REMARK.$SUBFIX
常用格式如上: $preifx
表示前綴,可在配置中指定,默認為 V
$version
表示 版本,中單可以使用 .
或 _
分隔,在解析時會將_
轉換為.
保存到schema_history
表的version
字段中;
$remark 表示備注,解析后會將這部分寫入到描述
字段中;
$subfix 表示后綴,可在配置中指定,默認為.sql
;
版本與描述之前使用__
分隔;
與spring boot的整合
- 在官網的文檔中找到插件部分:
- 在鏈接中找到spring boot
- 在spring boot插件與集成頁面中再選擇配置屬性
- 可以配置的屬性
到這里,與spring boot 整合的步驟就有了,加入pom依賴並配置相應的屬性即可;
引入maven依賴
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>5.2.4</version>
</dependency>
增加相應的配置
# 說明,在spring boot 1.x中,屬性前綴為flyway,在spring boot 2.x中為spring.flyway,需要區分不同版本
flyway:
# 到新的環境中數據庫中有數據,且沒有flyway_schema_history表時,是否執行遷移操作,如果設置為false,在啟動時會報錯,並停止遷移;如果為true,則生成history表並完成所有的遷移,要根據實際情況設置;
baseline-on-migrate: false
# 執行執行時標記的tag 默認為<<Flyway Baseline>>
baseline-description: <<Flyway Baseline>>
# 是否啟用flyway
enabled: true
# 檢測遷移腳本的路徑是否存在,如不存在,則拋出異常
check-location: true
# 腳本位置
locations: classpath:db/migration
# 在遷移時,是否校驗腳本,假設V1.0__初始.sql已經遷移過了,在下次啟動時會校驗該腳本是否有變更過,則拋出異常
validate-on-migrate: true
特別說明:如果非空數據庫遷移,在目標數據庫中手動建flyway_schema_history
表並手動寫入初始化的腳本記錄,使flyway跳過最初的校驗即可,后續可以保證版本的統一;
驗證
項目啟動有如下日志信息,表明校驗成功;
spring boot 中 flyway自動配置原理
spring boot 自動化配置,其中已經內置了flyway的功能;
spring boot 自動化配置的核心是Conditional
的幾個注解,根據注解來看,需要符合以下幾個條件:
- 存在
Flyway
的類; - 存在
Datasource
的類; - 存在
flyway
起始的配置屬性且enable
的屬性值為true;
//生成Flyway的實例
@Bean
@ConfigurationProperties(prefix = "flyway")
public Flyway flyway() {
Flyway flyway = new SpringBootFlyway();
if (this.properties.isCreateDataSource()) {
flyway.setDataSource(this.properties.getUrl(), this.properties.getUser(),
this.properties.getPassword(),
this.properties.getInitSqls().toArray(new String[0]));
}
else if (this.flywayDataSource != null) {
flyway.setDataSource(this.flywayDataSource);
}
else {
flyway.setDataSource(this.dataSource);
}
flyway.setLocations(this.properties.getLocations().toArray(new String[0]));
return flyway;
}
//生成FlywayMigrationInitializer的實例
@Bean
@ConditionalOnMissingBean
public FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
return new FlywayMigrationInitializer(flyway, this.migrationStrategy);
}
//這個類實現了InitalizingBean接口,可以在依賴注入完成后執行一些操作
public class FlywayMigrationInitializer implements InitializingBean, Ordered
//委托flyway對象完成數據庫的遷移命令,到這里,spring boot中flyway的操作完成.
@Override
public void afterPropertiesSet() throws Exception {
if (this.migrationStrategy != null) {
this.migrationStrategy.migrate(this.flyway);
}
else {
this.flyway.migrate();
}
}
<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">