diff --git a/lab-20/lab-20-database-version-control-flyway/pom.xml b/lab-20/lab-20-database-version-control-flyway/pom.xml
index faaa9fa3..c243f384 100644
--- a/lab-20/lab-20-database-version-control-flyway/pom.xml
+++ b/lab-20/lab-20-database-version-control-flyway/pom.xml
@@ -14,6 +14,7 @@
+
org.springframework.boot
spring-boot-starter-jdbc
@@ -24,10 +25,10 @@
5.1.48
+
org.flywaydb
flyway-core
- 5.2.4
diff --git a/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/ExampleFlywayCallback.java b/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/ExampleFlywayCallback.java
new file mode 100644
index 00000000..659392f9
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/ExampleFlywayCallback.java
@@ -0,0 +1,30 @@
+package cn.iocoder.springboot.lab20.databaseversioncontrol.migration;
+
+import org.flywaydb.core.api.callback.Callback;
+import org.flywaydb.core.api.callback.Context;
+import org.flywaydb.core.api.callback.Event;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ExampleFlywayCallback implements Callback {
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public boolean supports(Event event, Context context) {
+ return true;
+ }
+
+ @Override
+ public boolean canHandleInTransaction(Event event, Context context) {
+ return false;
+ }
+
+ @Override
+ public void handle(Event event, Context context) {
+ log.info("event: {}", event);
+ }
+
+}
diff --git a/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/V1_1__FixUsername.java b/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/V1_1__FixUsername.java
new file mode 100644
index 00000000..74b9a3d3
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-flyway/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/V1_1__FixUsername.java
@@ -0,0 +1,55 @@
+package cn.iocoder.springboot.lab20.databaseversioncontrol.migration;
+
+import org.flywaydb.core.api.MigrationVersion;
+import org.flywaydb.core.api.migration.BaseJavaMigration;
+import org.flywaydb.core.api.migration.Context;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowCallbackHandler;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class V1_1__FixUsername extends BaseJavaMigration {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public void migrate(Context context) throws Exception {
+ // 创建 JdbcTemplate ,方便 JDBC 操作
+ JdbcTemplate template = new JdbcTemplate(context.getConfiguration().getDataSource());
+ // 查询所有用户,如果用户名为 yudaoyuanma ,则变更成 yutou
+ template.query("SELECT id, username, password, create_time FROM users", new RowCallbackHandler() {
+ @Override
+ public void processRow(ResultSet rs) throws SQLException {
+ // 遍历返回的结果
+ do {
+ String username = rs.getString("username");
+ if ("yudaoyuanma".equals(username)) {
+ Integer id = rs.getInt("id");
+ template.update("UPDATE users SET username = ? WHERE id = ?",
+ "yutou", id);
+ logger.info("[migrate][更新 user({}) 的用户名({} => {})", id, username, "yutou");
+ }
+ } while (rs.next());
+ }
+ });
+ }
+
+ @Override
+ public Integer getChecksum() {
+ return 11; // 默认返回,是 null 。
+ }
+
+ @Override
+ public boolean canExecuteInTransaction() {
+ return true; // 默认返回,也是 true
+ }
+
+ @Override
+ public MigrationVersion getVersion() {
+ return super.getVersion(); // 默认按照约定的规则,从类名中解析获得。可以自定义
+ }
+
+}
diff --git a/lab-20/lab-20-database-version-control-flyway/src/main/resources/application.yaml b/lab-20/lab-20-database-version-control-flyway/src/main/resources/application.yaml
index c4041265..ff316839 100644
--- a/lab-20/lab-20-database-version-control-flyway/src/main/resources/application.yaml
+++ b/lab-20/lab-20-database-version-control-flyway/src/main/resources/application.yaml
@@ -1,15 +1,18 @@
spring:
# datasource 数据源配置内容,对应 DataSourceProperties 配置属性类
datasource:
- url: jdbc:mysql://127.0.0.1:3306/lab-19-flyway?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ url: jdbc:mysql://127.0.0.1:3306/lab-20-flyway?useSSL=false&useUnicode=true&characterEncoding=UTF-8
driver-class-name: com.mysql.jdbc.Driver
username: root # 数据库账号
password: # 数据库密码
-
+ # flyway 配置内容,对应 FlywayAutoConfiguration.FlywayConfiguration 配置项
flyway:
- enabled: true
- baseline-on-migrate: true
- locations: classpath:db/migration
- url: jdbc:mysql://127.0.0.1:3306/lab-19-flyway?useSSL=false&useUnicode=true&characterEncoding=UTF-8
- username: root
- password:
+ enabled: true # 开启 Flyway 功能
+ cleanDisabled: true # 禁用 Flyway 所有的 drop 相关的逻辑,避免出现跑路的情况。
+ locations: # 迁移脚本目录
+ - classpath:db/migration # 配置 SQL-based 的 SQL 脚本在该目录下
+ - classpath:cn.iocoder.springboot.lab20.databaseversioncontrol.migration # 配置 Java-based 的 Java 文件在该目录下
+ check-location: false # 是否校验迁移脚本目录下。如果配置为 true ,代表需要校验。此时,如果目录下没有迁移脚本,会抛出 IllegalStateException 异常
+ url: jdbc:mysql://127.0.0.1:3306/lab-20-flyway?useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
+ user: root # 数据库账号
+ password: # 数据库密码
diff --git a/lab-20/lab-20-database-version-control-flyway/src/main/resources/db/migration/V1.0__INIT_DB.sql b/lab-20/lab-20-database-version-control-flyway/src/main/resources/db/migration/V1.0__INIT_DB.sql
index 02a9b8eb..10a494ab 100644
--- a/lab-20/lab-20-database-version-control-flyway/src/main/resources/db/migration/V1.0__INIT_DB.sql
+++ b/lab-20/lab-20-database-version-control-flyway/src/main/resources/db/migration/V1.0__INIT_DB.sql
@@ -1,3 +1,4 @@
+-- 创建用户表
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
`username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号',
@@ -6,3 +7,6 @@ CREATE TABLE `users` (
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+
+-- 插入一条数据
+INSERT INTO `users`(username, password, create_time) VALUES('yudaoyuanma', 'password', now());
diff --git a/lab-20/lab-20-database-version-control-liquibase/pom.xml b/lab-20/lab-20-database-version-control-liquibase/pom.xml
new file mode 100644
index 00000000..4e978c99
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+ 4.0.0
+
+ lab-20-database-version-control-liquibase
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+
+
+
+
+
+ org.liquibase
+ liquibase-core
+
+
+
+
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/Application.java b/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/Application.java
new file mode 100644
index 00000000..ebb6f948
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/Application.java
@@ -0,0 +1,14 @@
+package cn.iocoder.springboot.lab20.databaseversioncontrol;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ // 启动 Spring Boot 应用
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/CHANGE_SET_3_FixUsername.java b/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/CHANGE_SET_3_FixUsername.java
new file mode 100644
index 00000000..c331cf7b
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/java/cn/iocoder/springboot/lab20/databaseversioncontrol/migration/CHANGE_SET_3_FixUsername.java
@@ -0,0 +1,57 @@
+package cn.iocoder.springboot.lab20.databaseversioncontrol.migration;
+
+import liquibase.change.custom.CustomTaskChange;
+import liquibase.database.Database;
+import liquibase.database.jvm.JdbcConnection;
+import liquibase.exception.CustomChangeException;
+import liquibase.exception.SetupException;
+import liquibase.exception.ValidationErrors;
+import liquibase.resource.ResourceAccessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+public class CHANGE_SET_3_FixUsername implements CustomTaskChange {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public void execute(Database database) throws CustomChangeException {
+ JdbcConnection connection = (JdbcConnection) database.getConnection();
+ try (PreparedStatement psmt = connection.prepareStatement("SELECT id, username, password, create_time FROM users")) {
+ try (ResultSet rs = psmt.executeQuery()) {
+ while (rs.next()) {
+ String username = rs.getString("username");
+ if ("yudaoyuanma".equals(username)) {
+ Integer id = rs.getInt("id");
+ // 这里,再来一刀更新操作,偷懒不写了。
+ logger.info("[migrate][更新 user({}) 的用户名({} => {})", id, username, "yutou");
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public String getConfirmationMessage() {
+ return null;
+ }
+
+ @Override
+ public void setUp() throws SetupException {
+ }
+
+ @Override
+ public void setFileOpener(ResourceAccessor resourceAccessor) {
+ }
+
+ @Override
+ public ValidationErrors validate(Database database) {
+ return null;
+ }
+
+}
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/resources/application.yaml b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/application.yaml
new file mode 100644
index 00000000..eb76689b
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/application.yaml
@@ -0,0 +1,14 @@
+spring:
+ # datasource 数据源配置内容,对应 DataSourceProperties 配置属性类
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/lab-20-liquibase?useSSL=false&useUnicode=true&characterEncoding=UTF-8
+ driver-class-name: com.mysql.jdbc.Driver
+ username: root # 数据库账号
+ password: # 数据库密码
+ # Liquibase 配置内容,对应 LiquibaseProperties 配置项
+ liquibase:
+ enabled: true # 开启 Liquibase 功能。默认为 true 。
+ change-log: classpath:/db/changelog/db.changelog-master.yaml # Liquibase 配置文件地址
+ url: jdbc:mysql://127.0.0.1:3306/lab-20-liquibase?useSSL=false&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
+ user: root # 数据库账号
+ password: # 数据库密码
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master-bak.yaml b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master-bak.yaml
new file mode 100644
index 00000000..7935ec2f
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master-bak.yaml
@@ -0,0 +1 @@
+databaseChangeLog:
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml
new file mode 100644
index 00000000..64e9f4bc
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/db.changelog-master.yaml
@@ -0,0 +1,62 @@
+databaseChangeLog:
+ - changeSet: # 对应一个 ChangeSet 对象
+ id: 0 # ChangeSet 编号
+ author: yunai # 作者
+ comments: 空 # 备注
+ - changeSet: # 对应一个 ChangeSet 对象
+ id: 1 # ChangeSet 编号
+ author: yunai # 作者
+ comments: 初始化 users 表 # 备注
+ changes: # 对应 Change 数组。Change 是一个接口,每种操作对应一种 Change 实现类
+ - createTable: # 创建表,对应 CreateTableChange 对象。
+ tableName: users # 表名
+ remarkds: 用户表 # 表注释
+ columns: # 对应 ColumnConfig 数组
+ - column:
+ name: id # 字段名
+ type: int # 字段类型
+ autoIncrement: true # 自增
+ constraints: # 限制条件,对应一个 ConstraintsConfig 对象
+ primaryKey: true # 主键
+ nullable: false # 不允许空
+ - column:
+ name: username
+ type: varchar(64)
+ constraints:
+ nullable: false
+ - column:
+ name: password
+ type: varchar(32)
+ constraints:
+ nullable: false
+ - column:
+ name: create_time
+ type: datetime
+ constraints:
+ nullable: false
+ - insert: # 插入记录,对应 InsertDataChange 对象。
+ tableName: users # 表名
+ columns: # 对应 ColumnConfig 数组
+ - column:
+ name: username # 字段名
+ value: yudaoyuanma # 值
+ - column:
+ name: password
+ value: password
+ - column:
+ name: create_time
+ value: now()
+ - changeSet: # 对应一个 ChangeSet 对象
+ id: 2 # ChangeSet 编号
+ author: yunai # 作者
+ comments: 初始化 users2 表 # 备注
+ changes: # 对应 Change 数组。Change 是一个接口,每种操作对应一种 Change 实现类
+ - sqlFile: # 使用 SQL 文件,对应 SQLFileChange 对象
+ encoding: utf8
+ path: classpath:db/changelog/sqlfile/CHAGE_SET_2_INIT_DB.sql
+ - changeSet: # 对应一个 ChangeSet 对象
+ id: 3 # ChangeSet 编号
+ author: yunai # 作者
+ comments: 修复 `users` 的用户名 # 备注
+ changes: # 对应 Change 数组。Change 是一个接口,每种操作对应一种 Change 实现类
+ - customChange: {class: cn.iocoder.springboot.lab20.databaseversioncontrol.migration.CHANGE_SET_3_FixUsername} # 对应 CustomTaskChange
diff --git a/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/sqlfile/CHAGE_SET_2_INIT_DB.sql b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/sqlfile/CHAGE_SET_2_INIT_DB.sql
new file mode 100644
index 00000000..327cdcf1
--- /dev/null
+++ b/lab-20/lab-20-database-version-control-liquibase/src/main/resources/db/changelog/sqlfile/CHAGE_SET_2_INIT_DB.sql
@@ -0,0 +1,12 @@
+-- 创建用户表
+CREATE TABLE `users2` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号',
+ `username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '账号',
+ `password` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密码',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `idx_username` (`username`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
+
+-- 插入一条数据
+INSERT INTO `users2`(username, password, create_time) VALUES('yudaoyuanma', 'password', now());
diff --git a/lab-20/pom.xml b/lab-20/pom.xml
index 8403ca71..5d21b3b7 100644
--- a/lab-20/pom.xml
+++ b/lab-20/pom.xml
@@ -14,6 +14,7 @@
lab-20-database-version-control
lab-20-database-version-control-flyway
+ lab-20-database-version-control-liquibase