一、核心依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<version>7.10.0</version>
</dependency>
</dependencies>
二、添加配置
Spring Boot 默认提供了对 Flyway 的自动配置:
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
所以,Spring Boot 项目,我们仅仅只要提供对应的配置参数即可:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/flyway
username: root
password: 123456
flyway:
locations:
- classpath:flyway
table: t_flyway_history
# 说明,在spring boot 1.x中,属性前缀为flyway,在spring boot 2.x中为spring.flyway,这里需要区分不同版本
Spring.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跳过最初的校验即可,后续可以保证版本的统一;
脚本文件名(对应flyway_schema_history表的script字段)定义规则:
常用格式如下:
$PREFIX$VERSION__$REMARK.$SUBFIX
说明:
$prefix 表示 前缀,可在配置中指定,默认为 V;
$version 表示 版本号,版本号中也可以使用 . 或 _分隔,在解析时会将 _ 转换为 . 再保存到flyway_schema_history表的version字段中;
$remark 表示 备注,解析后会将这部分写入到描述字段中;
$subfix 表示 后缀,可在配置中指定,默认为 .sql ;
版本号与备注之前使用__分隔;
例如: V20200307_01__initial.sql
****版本注意:
Spring Boot 2.5 及以上版本,如果使用了 spring.flyway.url 进行定义,同时需要加上 username/ password 进行认证。
如果是第一次使用 Flyway,需要在 resources 目录下创建配置文件中指定的 Flyway 迁移目录:resources/flyway。
-
Flyway 也是约定大于配置的思想,以上 Flyway 的相关配置都可以不用写,可以说是零配置,它们都有默认值:
spring.flyway.locations: classpath:db/migration,用于扫描的迁移脚本目录 spring.flyway.table: flyway_schema_history,用于记录所有的版本变化记录
-
更多 Flyway 的参数配置可以参考这个类:
org.springframework.boot.autoconfigure.flyway.FlywayProperties
三、迁移
1、创建迁移脚本
然后在该目录下创建迁移脚本,迁移脚本文件命名规则是:
V__.sql
注意:版本号后面是两个下划线。
如第一次创建三个迁移脚本:
V1.0.0__create_javastack.sql
V1.0.1__insert_javastack.sql
V1.0.2__update_javastack.sql
首先创建一个表,然后插入几条记录,再更新记录,具体的 SQL 脚本内容就不贴上来了,完整的示例代码已提交 Github:
https://github.com/javastacks/spring-boot-best-practice
OK,Spring Boot 集成 Flyway 及相关的脚本都弄完了,我们启动系统验证下脚本有没有执行。
1)首次启动
从启动日志可以看出,已经迁移了 3 个脚本,并且将当前版本更新到了 v1.0.2:
查看数据库,Flyway 历史表和业务表也都已经创建:
可以看出历史表记录了 3 个脚本的迁移详细记录,业务表的数据也已经插入并得到更新:
2)不修改再次启动
在不修改任何代码的情况下再次启动:
成功验证了 3 个迁移脚本,打印了当前的版本号,但并没有进行迁移,为什么?
因为这三个脚本都执行过迁移了,主要是版本号都小于等于当前版本号:1.0.2,所以不会进行迁移。
3)修改再次启动
我们再新增两个 SQL 脚本:
V1.0.3__alter_javastack.sql
V1.0.4__update_javastack.sql
首先新增两个字段:note 和 time,然后再进行对应的数据更新。
我们再次启动下:
成功迁移,当前版本来到了 v1.0.4。
查看数据库:
note 和 time 字段已经创建,并得到更新。
2、创建重复迁移脚本
从上面的例子我们知道,只要目录下的 SQL 脚本版本号大于当前版本号才会执行迁移,并且脚本都是一次性执行迁移的,如何做到可重复迁移呢?
Flyway 支持可重复迁移脚本,可重复迁移脚本文件命名规则是:
R__.sql
R(Repeated),即:可重复的。
这里我创建一个更新 note 和 time 字段的迁移脚本:
R__update_javastack.sql
1)首次启动
我们再次启动下:
从以上截图可以看到,重复迁移脚本也已经成功执行了。
2)不修改再次启动
如何确定能否重复执行迁移呢?
我们不修改任何代码再次启动下:
显示没有迁移的必要!!
那是因为我们没有对重复迁移脚本做任何的修改,所以系统不会迁移!
3)修改再次启动
我们再次改下脚本,把 note 后面加一个 ok,再次启动下:
脚本经过修改后再次迁移成功了,说明可重复迁移脚本也需要经过改动才能再次进行迁移,Flyway 会进行脚本对比。
最后贴一下迁移脚本目录:
这里我放到一个目录进行演示,实际开发中可以放到多个目录中区分维护。
四、迁移流程
1)Flyway 会扫描配置的脚本目录下的脚本文件;
2)如果历史记录表不存在,则新建历史记录表;
3)如果是一次性执行脚本(V),按版本号从小到大执行迁移脚本,与当前历史表中的版本号做对比,大于当前版本号的脚本才会被执行迁移;
4)如果是可重复执行脚本(R),检查脚本是否有变动,有变动的可重复脚本才会被执行迁移;
Flyway Migrate 迁移流程图:
另外,我们也可以手动删除迁移历史表中的迁移记录,这样也可以达到让一次性脚本再次执行的目的,但不建议在生产环境上进行使用。
五、总结
使用 Flyway 可以很方便的处理数据库表结果、数据的版本迁移,使用简单、自动化,大大提高生产力,再也不需要手工在控制台进行,那样更容易出错或者遗漏,毕竟人都是会经常犯错的。
本文使用的是 Java API 的方式,在项目启动时进行迁移,另外还有其他 3 种方式,文前有介绍,大家根据实际需要进行应用。
本文只是抛砖引玉,只介绍了 Flyway 中的 Migrate(迁移)环节,也是 Flyway 最主要的环节,另外还有其他 6 个环节,后续栈长在时间再进行分享,请陆续关注公众号Java技术栈,公众号第一时间推送。
本文完整示例代码已上传 Github:
https://github.com/javastacks/spring-boot-best-practice
更多细节可以参考官方文档:
https://flywaydb.org/documentation/
文章转载:https://www.cnblogs.com/javastack/p/14950066.html