|
| 1 | +# spring-boot-demo-flyway |
| 2 | + |
| 3 | +> 本 demo 演示了 Spring Boot 如何使用 Flyway 去初始化项目数据库,同时支持数据库脚本的版本控制。 |
| 4 | +
|
| 5 | +## 1. 添加依赖 |
| 6 | + |
| 7 | +- Flyway 依赖 |
| 8 | + |
| 9 | +```xml |
| 10 | +<!-- 添加 flyway 的依赖 --> |
| 11 | +<dependency> |
| 12 | + <groupId>org.flywaydb</groupId> |
| 13 | + <artifactId>flyway-core</artifactId> |
| 14 | +</dependency> |
| 15 | +``` |
| 16 | + |
| 17 | +- 初始化表结构,需要操作数据库,因此引入数据库驱动以及数据源依赖(这里用 spring-boot-starter-data-jdbc) |
| 18 | + |
| 19 | +```xml |
| 20 | +<dependency> |
| 21 | + <groupId>org.springframework.boot</groupId> |
| 22 | + <artifactId>spring-boot-starter-data-jdbc</artifactId> |
| 23 | +</dependency> |
| 24 | + |
| 25 | +<dependency> |
| 26 | + <groupId>mysql</groupId> |
| 27 | + <artifactId>mysql-connector-java</artifactId> |
| 28 | + <scope>runtime</scope> |
| 29 | +</dependency> |
| 30 | +``` |
| 31 | + |
| 32 | +## 2. Flyway 知识补充 |
| 33 | + |
| 34 | +1. Flyway 默认会去读取 `classpath:db/migration`,可以通过 `spring.flyway.locations` 去指定自定义路径,多个路径使用半角英文逗号分隔,内部资源使用 `classpath:`,外部资源使用 `file:` |
| 35 | + |
| 36 | +2. 如果项目初期没有数据库文件,但是又引用了 Flyway,那么在项目启动的时候,Flyway 会去检查是否存在 SQL 文件,此时你需要将这个检查关闭,`spring.flyway.check-location = false` |
| 37 | + |
| 38 | +3. Flyway 会在项目初次启动的时候创建一张名为 `flyway_schema_history` 的表,在这张表里记录数据库脚本执行的历史记录,当然,你可以通过 `spring.flyway.table` 去修改这个值 |
| 39 | + |
| 40 | +4. Flyway 执行的 SQL 脚本必须遵循一种命名规则,`V<VERSION>__<NAME>.sql` 首先是 `V` ,然后是版本号,如果版本号有多个数字,使用`_`分隔,比如`1_0`、`1_1`,版本号的后面是 2 个下划线,最后是 SQL 脚本的名称。 |
| 41 | + |
| 42 | + **这里需要注意:V 开头的只会执行一次,下次项目启动不会执行,也不可以修改原始文件,否则项目启动会报错,如果需要对 V 开头的脚本做修改,需要清空`flyway_schema_history`表,如果有个 SQL 脚本需要在每次启动的时候都执行,那么将 V 改为 `R` 开头即可** |
| 43 | + |
| 44 | +5. Flyway 默认情况下会去清空原始库,再重新执行 SQL 脚本,这在生产环境下是不可取的,因此需要将这个配置关闭,`spring.flyway.clean-disabled = true` |
| 45 | + |
| 46 | +## 3. application.yml 配置 |
| 47 | + |
| 48 | +> 贴出我的 application.yml 配置 |
| 49 | +
|
| 50 | +```yaml |
| 51 | +spring: |
| 52 | + flyway: |
| 53 | + enabled: true |
| 54 | + # 迁移前校验 SQL 文件是否存在问题 |
| 55 | + validate-on-migrate: true |
| 56 | + # 生产环境一定要关闭 |
| 57 | + clean-disabled: true |
| 58 | + # 校验路径下是否存在 SQL 文件 |
| 59 | + check-location: false |
| 60 | + datasource: |
| 61 | + url: jdbc:mysql://127.0.0.1:3306/flyway-test?useSSL=false |
| 62 | + username: root |
| 63 | + password: root |
| 64 | + type: com.zaxxer.hikari.HikariDataSource |
| 65 | +``` |
| 66 | +
|
| 67 | +## 4. 测试 |
| 68 | +
|
| 69 | +### 4.1. 测试 1.0 版本的 SQL 脚本 |
| 70 | +
|
| 71 | +创建 `V1_0__INIT.sql` |
| 72 | + |
| 73 | +```mysql |
| 74 | +DROP TABLE IF EXISTS `t_user`; |
| 75 | +CREATE TABLE `t_user` ( |
| 76 | + `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', |
| 77 | + `username` varchar(32) NOT NULL COMMENT '用户名', |
| 78 | + `password` varchar(32) NOT NULL COMMENT '加密后的密码', |
| 79 | + `salt` varchar(32) NOT NULL COMMENT '加密使用的盐', |
| 80 | + `email` varchar(32) NOT NULL COMMENT '邮箱', |
| 81 | + `phone_number` varchar(15) NOT NULL COMMENT '手机号码', |
| 82 | + `status` int(2) NOT NULL DEFAULT '1' COMMENT '状态,-1:逻辑删除,0:禁用,1:启用', |
| 83 | + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', |
| 84 | + `last_login_time` datetime DEFAULT NULL COMMENT '上次登录时间', |
| 85 | + `last_update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上次更新时间', |
| 86 | + PRIMARY KEY (`id`), |
| 87 | + UNIQUE KEY `username` (`username`), |
| 88 | + UNIQUE KEY `email` (`email`), |
| 89 | + UNIQUE KEY `phone_number` (`phone_number`) |
| 90 | +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='1.0-用户表'; |
| 91 | +``` |
| 92 | + |
| 93 | +启动项目,可以看到日志输出: |
| 94 | + |
| 95 | +```java |
| 96 | +2020-03-05 10:48:37.799 INFO 3351 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.1 by Boxfuse |
| 97 | +2020-03-05 10:48:37.802 INFO 3351 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... |
| 98 | +2020-03-05 10:48:37.971 INFO 3351 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. |
| 99 | +2020-03-05 10:48:37.974 INFO 3351 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:mysql://127.0.0.1:3306/flyway-test (MySQL 5.7) |
| 100 | +2020-03-05 10:48:38.039 INFO 3351 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 1 migration (execution time 00:00.015s) |
| 101 | +2020-03-05 10:48:38.083 INFO 3351 --- [ main] o.f.c.i.s.JdbcTableSchemaHistory : Creating Schema History table: `flyway-test`.`flyway_schema_history` |
| 102 | +2020-03-05 10:48:38.143 INFO 3351 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `flyway-test`: << Empty Schema >> |
| 103 | +2020-03-05 10:48:38.144 INFO 3351 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway-test` to version 1.0 - INIT |
| 104 | +2020-03-05 10:48:38.156 WARN 3351 --- [ main] o.f.c.i.s.DefaultSqlScriptExecutor : DB: Unknown table 'flyway-test.t_user' (SQL State: 42S02 - Error Code: 1051) |
| 105 | +2020-03-05 10:48:38.183 INFO 3351 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `flyway-test` (execution time 00:00.100s) |
| 106 | +``` |
| 107 | + |
| 108 | +检查数据库,发现创建了 2 张表,一张是 Flyway 依赖的历史表,另一张就是我们的 `t_user` 表 |
| 109 | + |
| 110 | +<img src="assets/image-20200305105632047.png" alt="image-20200305105632047" style="zoom:50%;" /> |
| 111 | + |
| 112 | +查看下 `flyway-schema-history` 表 |
| 113 | + |
| 114 | +<img src="assets/image-20200305110147176.png" alt="image-20200305110147176" style="zoom:50%;" /> |
| 115 | + |
| 116 | +### 4.2. 测试 1.1 版本的 SQL 脚本 |
| 117 | + |
| 118 | +创建 `V1_1__ALTER.sql` |
| 119 | + |
| 120 | +```mysql |
| 121 | +ALTER TABLE t_user COMMENT = '用户 v1.1'; |
| 122 | +``` |
| 123 | + |
| 124 | +启动项目,可以看到日志输出: |
| 125 | + |
| 126 | +```java |
| 127 | +2020-03-05 10:59:02.279 INFO 3536 --- [ main] o.f.c.internal.license.VersionPrinter : Flyway Community Edition 5.2.1 by Boxfuse |
| 128 | +2020-03-05 10:59:02.282 INFO 3536 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... |
| 129 | +2020-03-05 10:59:02.442 INFO 3536 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. |
| 130 | +2020-03-05 10:59:02.445 INFO 3536 --- [ main] o.f.c.internal.database.DatabaseFactory : Database: jdbc:mysql://127.0.0.1:3306/flyway-test (MySQL 5.7) |
| 131 | +2020-03-05 10:59:02.530 INFO 3536 --- [ main] o.f.core.internal.command.DbValidate : Successfully validated 2 migrations (execution time 00:00.018s) |
| 132 | +2020-03-05 10:59:02.538 INFO 3536 --- [ main] o.f.core.internal.command.DbMigrate : Current version of schema `flyway-test`: 1.0 |
| 133 | +2020-03-05 10:59:02.538 INFO 3536 --- [ main] o.f.core.internal.command.DbMigrate : Migrating schema `flyway-test` to version 1.1 - ALTER |
| 134 | +2020-03-05 10:59:02.564 INFO 3536 --- [ main] o.f.core.internal.command.DbMigrate : Successfully applied 1 migration to schema `flyway-test` (execution time 00:00.029s) |
| 135 | +``` |
| 136 | + |
| 137 | +检查数据库,可以发现 `t_user` 表的注释已经更新 |
| 138 | + |
| 139 | +<img src="assets/image-20200305105958181.png" alt="image-20200305105958181" style="zoom:50%;" /> |
| 140 | + |
| 141 | +查看下 `flyway-schema-history` 表 |
| 142 | + |
| 143 | +<img src="assets/image-20200305110057768.png" alt="image-20200305110057768" style="zoom:50%;" /> |
| 144 | + |
| 145 | +## 参考 |
| 146 | + |
| 147 | +1. [Spring Boot 官方文档 - Migration 章节](https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#howto-execute-flyway-database-migrations-on-startup) |
| 148 | +2. [Flyway 官方文档](https://flywaydb.org/documentation/) |
0 commit comments