SpringBoot-Flyway父子项目配置
参考文献
背景说明
- 由于公司架构升级,需要把部分组件抽离出来重构,需要抽离出一个所有组件的父组件项目来统一管理其他组件公共的功能模块或者依赖等.父组件项目由于有些配置项需要灵活配置,故而将这些配置项放入数据库表中进行管理.所以这边采用
Flyway
框架来管理这些SQL
. - 但由于父组件和子组件都需要使用
Flyway
框架,因此对此进行调查研究一下.
环境说明
-
父子项目A和B,A为父项目,B为子项目.
-
父子项目都为SpringBoot项目.
-
JDK版本为11
-
SpringBoot版本如下所示:
1
2
3
4
5
6<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> -
Flyway版本如下所示:
1
2
3
4
5
6<!-- flyway.version为8.0.2-->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>${flyway.version}</version>
</dependency> -
数据库采用MySQL 8.0
-
父项目测试脚本文件名为
BASE_1.0.0.0__INIT_TABLE.sql
,其本身没有内容. -
子项目测试脚本文件名为
DICOM_1.0.0.0__CREATE_DICOM_TAG_TABLE.sql
,其内容如下(即会创建一张名为dicom_tag
的表)1
2
3
4
5
6
7
8
9
10
11
12
13
14DROP TABLE
IF
EXISTS `dicom_tag`;
CREATE TABLE `dicom_tag` (
`id` INT auto_increment NOT NULL,
`flag` VARCHAR ( 100 ) NOT NULL COMMENT 'Tag标识',
`coordinates` CHAR ( 11 ) NOT NULL COMMENT 'Tag标准坐标',
`tag_value` int NOT NULL COMMENT '程序对应的Tag值',
`need_check` TINYINT NOT NULL DEFAULT 0 COMMENT '是否需要校验,0-无需校验;1-需要校验',
`value_type` VARCHAR ( 50 ) NOT NULL COMMENT 'Tag值的数据类型',
`description` text NULL COMMENT 'Tag描述',
PRIMARY KEY ( `id` ),
UNIQUE KEY ( `flag` )
);
配置说明
-
父子项目同时使用
Flyway
,父项目需要手动配置Flyway Bean
以及配置Flyway
迁移策略,子项目需要手动配置
Flyway Bean
-
父项目
Flyway Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package cn.holelin.flywaybase.config;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: 基础Flyway配置类
* @Author: HoleLin
* @CreateDate: 2022/5/3 6:28 PM
* @UpdateUser: HoleLin
* @UpdateDate: 2022/5/3 6:28 PM
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
public class FlywayBaseMigrationConfig {
public FluentConfiguration moduleBaseFlywayMigrationConfig() {
return Flyway.configure()
.sqlMigrationPrefix("BASE_")
.table("flyway_base_schema_history")
.locations("db/migration/base");
}
} -
配置
Flyway
迁移策略1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package cn.holelin.flywaybase.config;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: 基础Flyway迁移策略
* @Author: HoleLin
* @CreateDate: 2022/5/3 6:28 PM
* @UpdateUser: HoleLin
* @UpdateDate: 2022/5/3 6:28 PM
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
public class FlywayBaseMigrationStrategy implements FlywayMigrationStrategy {
private List<FluentConfiguration> migrations;
public void migrate(Flyway flyway) {
this.migrations.forEach(mig -> mig.
baselineOnMigrate(true).
baselineVersion("0").
dataSource(flyway.getConfiguration().getDataSource()).
load().
migrate())
}
} -
子项目
Flyway Bean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package cn.holelin.dicom.config;
import org.flywaydb.core.Flyway;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.flyway.FlywayProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: 子项目Flyway配置类
* @Author: HoleLin
* @CreateDate: 2022/5/3 6:28 PM
* @UpdateUser: HoleLin
* @UpdateDate: 2022/5/3 6:28 PM
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
public class FlywayMigrationConfig {
private FlywayProperties flywayProperties;
public FluentConfiguration moduleFlywayMigrationConfig() {
return Flyway.configure()
.sqlMigrationPrefix(flywayProperties.getSqlMigrationPrefix())
.table(flywayProperties.getTable())
.locations(String.join(",",flywayProperties.getLocations()));
}
} -
若不在父项目中配置
Flyway Bean
以及Flyway
迁移策略的话,会导致父项目在被子项目继承或者引用时,启动子项目后,只有子项目中被Flyway
管理的脚本被执行,父项目的Flyway
所管理的脚本无法被执行.1
2
3
4
5
6
7
8
9
102022-05-04 01:03:14.921 INFO 19283 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.0.2 by Redgate
2022-05-04 01:03:14.921 INFO 19283 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://localhost:3306/dicom (MySQL 8.0)
2022-05-04 01:03:14.947 INFO 19283 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.011s)
2022-05-04 01:03:14.964 INFO 19283 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `dicom`.`flyway_schema_history` ...
2022-05-04 01:03:15.010 INFO 19283 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `dicom`: << Empty Schema >>
2022-05-04 01:03:15.014 INFO 19283 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `dicom` to version "1.0.0.0 - CREATE DICOM TAG TABLE"
2022-05-04 01:03:15.022 WARN 19283 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Unknown table 'dicom.dicom_tag' (SQL State: 42S02 - Error Code: 1051)
2022-05-04 01:03:15.038 INFO 19283 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `dicom`, now at version v1.0.0.0 (execution time 00:00.030s)
2022-05-04 01:03:15.090 INFO 19283 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-04 01:03:15.096 INFO 19283 --- [ main] cn.holelin.dicom.DicomApplication : Started DicomApplication in 1.213 seconds (JVM running for 1.715)- 由上述打印的日志,可以发现只有子项目的脚本被执行了.
-
若只在父项目中配置
Flyway Bean
以及Flyway
迁移策略,子项目不配置Flyway Bean
则会导致,只有父项目的脚本被执行.1
2
3
4
5
6
7
8
92022-05-04 00:58:58.380 INFO 19118 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.0.2 by Redgate
2022-05-04 00:58:58.380 INFO 19118 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://localhost:3306/dicom (MySQL 8.0)
2022-05-04 00:58:58.403 INFO 19118 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.006s)
2022-05-04 00:58:58.415 INFO 19118 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `dicom`.`flyway_base_schema_history` ...
2022-05-04 00:58:58.454 INFO 19118 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `dicom`: << Empty Schema >>
2022-05-04 00:58:58.457 INFO 19118 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `dicom` to version "1.0.0.0 - INIT TABLE"
2022-05-04 00:58:58.467 INFO 19118 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `dicom`, now at version v1.0.0.0 (execution time 00:00.015s)
2022-05-04 00:58:58.519 INFO 19118 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-04 00:58:58.526 INFO 19118 --- [ main] cn.holelin.dicom.DicomApplication : Started DicomApplication in 1.091 seconds (JVM running for 1.449)- 由上述日志中,可以发现
Flyway
成功迁移了父项目的1.0.0.0 - INIT TABLE
脚本,但是子项目的脚本为成功执行.
- 由上述日志中,可以发现
-
父子项目都配置完毕后,其输出的日志,数据库中创建的表以及
Flyway
执行脚本记录表的内容如下所示:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
182022-05-04 01:16:56.035 INFO 20535 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.0.2 by Redgate
2022-05-04 01:16:56.036 INFO 20535 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://localhost:3306/dicom (MySQL 8.0)
2022-05-04 01:16:56.064 INFO 20535 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.016s)
2022-05-04 01:16:56.086 INFO 20535 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `dicom`.`flyway_schema_history` ...
2022-05-04 01:16:56.120 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `dicom`: << Empty Schema >>
2022-05-04 01:16:56.124 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `dicom` to version "1.0.0.0 - CREATE DICOM TAG TABLE"
2022-05-04 01:16:56.132 WARN 20535 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Unknown table 'dicom.dicom_tag' (SQL State: 42S02 - Error Code: 1051)
2022-05-04 01:16:56.149 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `dicom`, now at version v1.0.0.0 (execution time 00:00.032s)
2022-05-04 01:16:56.156 INFO 20535 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 8.0.2 by Redgate
2022-05-04 01:16:56.156 INFO 20535 --- [ main] o.f.c.i.database.base.BaseDatabaseType : Database: jdbc:mysql://localhost:3306/dicom (MySQL 8.0)
2022-05-04 01:16:56.163 INFO 20535 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.001s)
2022-05-04 01:16:56.176 INFO 20535 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table `dicom`.`flyway_base_schema_history` with baseline ...
2022-05-04 01:16:56.192 INFO 20535 --- [ main] o.f.core.internal.command.DbBaseline : Successfully baselined schema with version: 0
2022-05-04 01:16:56.194 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `dicom`: 0
2022-05-04 01:16:56.196 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `dicom` to version "1.0.0.0 - INIT TABLE"
2022-05-04 01:16:56.202 INFO 20535 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `dicom`, now at version v1.0.0.0 (execution time 00:00.009s)
2022-05-04 01:16:56.245 INFO 20535 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-05-04 01:16:56.251 INFO 20535 --- [ main] cn.holelin.dicom.DicomApplication : Started DicomApplication in 1.23 seconds (JVM running for 1.631)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48mysql> show tables;
+----------------------------+
| Tables_in_dicom |
+----------------------------+
| dicom_tag |
| flyway_base_schema_history |
| flyway_schema_history |
+----------------------------+
3 rows in set (0.00 sec)
mysql> select * from flyway_base_schema_history\G
*************************** 1. row ***************************
installed_rank: 1
version: 0
description: << Flyway Baseline >>
type: BASELINE
script: << Flyway Baseline >>
checksum: NULL
installed_by: root
installed_on: 2022-05-04 01:16:56
execution_time: 0
success: 1
*************************** 2. row ***************************
installed_rank: 2
version: 1.0.0.0
description: INIT TABLE
type: SQL
script: BASE_1.0.0.0__INIT_TABLE.sql
checksum: 0
installed_by: root
installed_on: 2022-05-04 01:16:56
execution_time: 1
success: 1
2 rows in set (0.00 sec)
mysql> select * from flyway_schema_history\G
*************************** 1. row ***************************
installed_rank: 1
version: 1.0.0.0
description: CREATE DICOM TAG TABLE
type: SQL
script: DICOM_1.0.0.0__CREATE_DICOM_TAG_TABLE.sql
checksum: 115451493
installed_by: root
installed_on: 2022-05-04 01:16:56
execution_time: 12
success: 1
1 row in set (0.00 sec) -
TIPS: 父子项目创建的时,建议包名前缀保持一致.
示例
父项目
-
其主要文件目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── cn
│ │ │ └── holelin
│ │ │ └── flywaybase
│ │ │ ├── FlywayBaseApplication.java
│ │ │ └── config
│ │ │ ├── FlywayBaseMigrationConfig.java
│ │ │ └── FlywayBaseMigrationStrategy.java
│ │ └── resources
│ │ ├── application.yml
│ │ └── db
│ │ └── migration
│ │ └── base
│ │ └── BASE_1.0.0.0__INIT_TABLE.sql -
FlywayBaseMigrationConfig
类中内容即为手动定义的Flyway Bean
,FlywayBaseMigrationStrategy
即为迁移策略
子项目
-
其主要文件目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── cn
│ │ │ └── holelin
│ │ │ └── dicom
│ │ │ ├── DicomApplication.java
│ │ │ ├── config
│ │ │ │ └── FlywayMigrationConfig.java
│ │ └── resources
│ │ ├── application.yml
│ │ ├── db
│ │ │ └── migration
│ │ │ └── DICOM_1.0.0.0__CREATE_DICOM_TAG_TABLE.sql -
FlywayMigrationConfig
即为子项目的Flyway Bean
-
其中
DicomApplication
中需要手动指定SpringBoot扫描Bean的包路径,保证父项目中创建的Bean被加入到Spring容器中,其代码如下:1
2
3
4
5
6
7
8
9
10
11
12package cn.holelin.dicom;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
public class DicomApplication {
public static void main(String[] args) {
SpringApplication.run(DicomApplication.class, args);
}
}