Flyway是一个开源的数据库迁移工具。与配置相比,Flyway极力主张简单和约定。它仅基于7个基本命令: 迁移, 清理, 信息, 验证, 撤消, 基线和 修复。
迁移可以用SQL (支持特定于数据库的语法(例如PL / SQL,T-SQL等)或Java (适用于高级数据转换或处理LOB)的方式编写。
支持的数据库包括 Oracle, SQL Server(包括Amazon RDS和Azure SQL数据库), DB2, MySQL(包括Amazon RDS,Azure数据库和Google Cloud SQL), Aurora MySQL, MariaDB, Percona XtraDB群集, PostgreSQL(包括Amazon RDS,Azure数据库) ,Google Cloud SQL和Heroku), Aurora PostgreSQL, Redshift, CockroachDB, SAP HANA, Sybase ASE, Informix, H2, HSQLDB, Derby, Snowflake, SQLite和 Firebird。
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.flywaydbgroupId>
<artifactId>flyway-coreartifactId>
<version>5.2.1version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.13version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.16version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.flywaydbgroupId>
<artifactId>flyway-maven-pluginartifactId>
<version>5.0.3version>
plugin>
plugins>
build>
# application.yml
server:
port: 8088
spring:
profiles:
active: dev
# application-dev.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/testdb?serverTimezone=GMT%2B8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
flyway:
baseline-on-migrate: true
# locations: classpath:db/migration # 迁移脚本的路径
enabled: true # 是否开启flyway
validationQuery: SELECT 1
type: com.alibaba.druid.pool.DruidDataSource
flyway迁移脚本(.sql文件)默认放在classpath: db/migration文件夹中
启动项目flyway创建版本管理表flyway_schema_history
,并遍历db.migraion
目录下数据库sql文件。
flyway在执行脚本时,会在源数据表中检查checksum值,并确定上次运行运行到哪一个脚本文件,本次执行时从下一条脚本文件开始执行。
所以需要注意下:
编写脚本的时候不要去修改原有的脚本内容
新的脚本版本号要连续,如果需要重复修改执行脚本可以使用repeatable migration(可重复迁移),编写的sql语句为可重复升级语句。
这里建议多人开发时,先使用
repeatable migration
模式对一个脚本进行开发,当应用程序发版的时候在定一个Versioned Migrations
模式的版本。
文件名格式规定
V
+版本号
+__
+描述
+.sql
R
+__
+描述
+.sql
具体要求:
使用Flyway升级,flyway会自动创建一张历史记录表:flyway_schema_history。
java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to utilize time zone support.
在数据库连接地址后边加上时区,例如
url: jdbc:mysql://localhost:3306/testdb?serverTimezone=GMT%2B8
程序第一次运行时,并没有手动创建数据库(schema),但是flyway的操作是在已存在的数据库中进行,否则会报错。
可以使用druid配合创建。
package com.felton.springbootflyway.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
@Configuration
@Primary //在同样的DataSource中,首先使用被标注的DataSource
public class DataSourceConfig {
// private Logger log = LoggerFactory.getLogger(DataSourceConfig.class);
@Value("${spring.datasource.url}")
//jdbc:mysql://127.0.0.1:3306/insight?useUnicode=true&characterEncoding=utf8&failOverReadOnly=false&allowMultiQueries=true
private String datasourceUrl;
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Bean //声明其为Bean实例
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(datasourceUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
try {
Class.forName(driverClassName);
String url01 = datasourceUrl.substring(0, datasourceUrl.indexOf("?"));
String url02 = url01.substring(0, url01.lastIndexOf("/"))+"?serverTimezone=GMT%2B8";
String datasourceName = url01.substring(url01.lastIndexOf("/") + 1);
// 连接已经存在的数据库,如:mysql
Connection connection = DriverManager.getConnection(url02, username, password);
Statement statement = connection.createStatement();
// 创建数据库
statement.executeUpdate("create database if not exists `" + datasourceName + "` default character set utf8 COLLATE utf8_general_ci");
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
return datasource;
}
}