- 官网:https://flywaydb.org/
image.png
从官网可以看到,flyway主要是为了数据库迁移的,通过版本控制使得迁移的时候更加便利,即数据库版本管理工具。
1. 介绍
为什么要使用Flyway?
我们的源代码可以通过Git或是其它版本控制工具来管理,那么数据库迭代,每次都需要手动在本地,或是测试环境或是线上进行手动execute,这样是极其不方便以及容易不错的。
Flyway的workflow:
官网:https://flywaydb.org/documentation/command/migrate
![](https://img.haomeiwen.com/i15522532/cf0c65d276d3d67b.png)
- Flyway在初始运行时会自动新建一张表:
flyway_schema_history
。 - 在做迁移的时候,Flyway会扫描程序classpath下的文件,然后对比这些文件是否已经被执行到数据库中了,如果发现有不同的,那么Flyway就会执行以便使得classpath下的文件的内容被更新到数据库中。
- Flyway会在程序启动的时候就做迁移工作。
- Flyway的执行过程是幂等的,即可以重复被执行,如我们的测试环境可能因为bug等原因会被重复部署也没有关系。
- Flyway会按version顺序执行,比如我们迁移需要到version9,数据库端才到version5,那么迁移的执行会从6开始,顺序到7,8,9。再比如迁移需要到9,而数据库端已经到9了,那么迁移就不会重复执行。
2. 例子:与Spring Boot 2集成
参考:https://www.techgeeknext.com/spring-boot/spring-boot-flyway-example
2.1 依赖
我用的是Spring Boot v2.3.1。(没用2.7.0的主要原因是对应的flyway-core版本v8.5.11太高了,支持不了我本地的mysql 5.7)。而Spring Boot v2.3.1对应的flyway-core版本是v6.4.4,可以支持mysql 5.7。
除了web starter,还加了spring-boot-starter-data-jpa,以及mysql的依赖(用的是v5.1.18),除此之外,加上flyway的依赖:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
JPA相关
Course类:
@Data
@Entity
@Table(name = "COURSE")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "name")
private String name;
}
CourseRepository类:
public interface CourseRepository extends JpaRepository<Course, Integer> {
}
application.properties配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/flyway_test?useUnicode=true&characterEncoding=UTF-8
username: root
password: xxxxxx
driver-class-name: com.mysql.jdbc.Driver
2.3 Flyway script
默认情况下,Flyway会读取db/migration
下的文件。
我们在src/main/resources/db/migration
目录下, 新建文件:V1__init.sql
:
![](https://img.haomeiwen.com/i15522532/c829abad818a8b79.png)
CREATE TABLE `course` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
2.4 测试
启动项目后,可以看到Flyway自动创建了表flyway_schema_history
:
![](https://img.haomeiwen.com/i15522532/7b9a5c7bc8f27ac7.png)
表flyway_schema_history
截图如下:
![](https://img.haomeiwen.com/i15522532/95849587513e1c24.png)
可以看到在表中,会记录version,script文件名以及每次需要检查是否有改动的列checksum,是否成功等字段。
如果我们修改了V1__init.sql
,再次启动程序后,Flyway会先对比checksum,如果发现该文件有改动,那么Flyway就会报错:
Caused by: org.flywaydb.core.api.FlywayException: Validate failed:
Migration checksum mismatch for migration version 1
-> Applied to database : 665192092
-> Resolved locally : -411806854
也就是说每次新的改动,需要我们新建一个新的script文件,比如叫V2__init.sql
,这样在启动的时候Flyway就会识别并执行了。
2.5 加上更多的Flyway script
新建一个script文件,叫V2__init.sql
,在这个文件中,我们尝试对course表增加一列status:
ALTER TABLE `flyway_test`.`course`
ADD COLUMN `status` VARCHAR(45) NULL AFTER `name`;
再次启动程序,可以看到status自动加上了:
![](https://img.haomeiwen.com/i15522532/5d10f7de7696ee14.png)
而表flyway_schema_history
也会多一行记录:
![](https://img.haomeiwen.com/i15522532/b45a7784eebd59b3.png)
当然我们也可以在script中加一些insert等插入语句。
2.6 测试,同时执行多份sql
首先我们将表flyway_schema_history
和course
删掉。
修改下script文件的名字(没别的意义,主要是测试用):
![](https://img.haomeiwen.com/i15522532/7d34b2f89fbc303c.png)
启动程序,Flyway会依次执行script脚本(version升序),script文件命名规则:以大写的"V"开头 + 版本号(版本号的数字间以”.“或”_“分隔开),+ 双下划线(用来分隔版本号和描述) + 文件描述 + 后缀名
。
如V1__init.sql,或V1_1_0__my_first_migration.sql
![](https://img.haomeiwen.com/i15522532/f9a8a06d9fc1a672.png)
2.7 关闭Flyway
有时候在本地或是测试环境,我们需要Flyway自动生成表或是修改表结构,而在生产环境,为了保险起见需要手动审核并执行,那么可以通过以下属性进行关闭:
spring.flyway.enabled=false
3. Flyway Maven插件
Flyway有maven的插件,可以通过绑定特定的生命周期使得只执行migration,而不是通过程序启动等方式执行。
具体查看官网:https://flywaydb.org/documentation/getstarted/firststeps/maven
<plugins>
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
</plugin>
</plugins>
网友评论