Spring Boot使用 Flyway 进行数据库迁移

x33g5p2x  于10个月前 转载在 Spring  
字(5.3k)|赞(0)|评价(0)|浏览(143)

第一次建造时,没有什么是完美和完整的。全新应用程序的数据库架构也不例外。当您尝试适应新需求或添加新功能时,它必然会随着时间而改变。

Flyway 是一种工具,可让您对数据库的增量更改进行版本控制,以便您可以轻松自信地将其迁移到新版本。

在本文中,您将学习如何在 Spring Boot 应用程序中使用 Flyway 来管理对数据库的更改。

我们将使用 MySQL 数据库和 Spring Data JPA 构建一个简单的 Spring Boot 应用程序,并学习如何在应用程序中集成 Flyway。

让我们开始吧!

创建应用程序

让我们使用 Spring Boot CLI 来生成应用程序。启动终端并键入以下命令以生成项目。

spring init --name=flyway-demo --dependencies=web,mysql,data-jpa,validation,flyway flyway-demo

项目生成后,将其导入您喜欢的 IDE。应用程序的目录结构如下所示 -

配置 MySQL 和 Hibernate

首先创建一个名为 flyway_demo 的新 MySQL 数据库。

然后 打开 src/main/application.properties 文件并向其添加以下属性 -

## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/flyway_demo?useSSL=false
spring.datasource.username = root
spring.datasource.password = root

## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

## This is important
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = validate

请根据您的 MySQL 安装更改 spring.datasource.usernamespring.datasource.password

属性 spring.jpa.hibernate.ddl-auto 很重要。它尝试根据您在应用程序中创建的实体来验证数据库架构,如果架构与实体规范不匹配,则会引发错误。

创建域实体

让我们在我们的应用程序中创建一个简单的实体,以便我们可以为这个实体创建和测试飞行路线迁移。

首先,在 com.example.flywaydemo 包中创建一个名为 domain 的新包。 然后,在 com.example.flywaydemo.domain 包中创建以下 User.java 文件 -

package com.example.flywaydemo.domain;

import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    @Column(unique = true)
    @Size(min = 1, max = 100)
    private String username;

    @NotBlank
    @Size(max = 50)
    private String firstName;

    @Size(max = 50)
    private String lastName;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

创建 Flyway 迁移脚本

默认情况下,Flyway 尝试从 classpath:db/migration 文件夹读取数据库迁移脚本。

所有迁移脚本都必须遵循特定的命名约定 - V<VERSION_NUMBER>__<NAME>.sql。查看官方 Flyway 文档以了解有关命名约定的更多信息。

让我们创建我们的第一个数据库迁移脚本。首先,在 src/main/resources 目录中创建 db/migration 文件夹 -

mkdir -p src/main/resources/db/migration

现在,在 src/main/resources/db/migration 目录中创建一个名为 V1__init.sql 的新文件,并添加以下 sql 脚本 -

CREATE TABLE users (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  username varchar(100) NOT NULL,
  first_name varchar(50) NOT NULL,
  last_name varchar(50) DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY UK_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

运行应用程序

当您运行应用程序时,flyway 将自动检查当前数据库版本并应用任何挂起的迁移。

通过在终端中键入以下命令来运行应用程序 -

mvn spring-boot:run

首次运行该应用程序时,您将看到以下有关 Flyway 的日志,其中表示已将架构迁移到版本 1 - init。

Flyway 如何管理迁移?

Flyway 在第一次运行迁移时会创建一个名为 flyway_schema_history 的表,并将版本化迁移所需的所有元数据存储在该表中。

mysql> show tables;
+-----------------------+
| Tables_in_flyway_demo |
+-----------------------+
| flyway_schema_history |
| users                 |
+-----------------------+
2 rows in set (0.00 sec)

您可以检查 mysql 数据库中 flyway_schema_history 表的内容 -

mysql> select * from flyway_schema_history;
+----------------+---------+-------------+------+--------------+------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description | type | script       | checksum   | installed_by | installed_on        | execution_time | success |
+----------------+---------+-------------+------+--------------+------------+--------------+---------------------+----------------+---------+
|              1 | 1       | init        | SQL  | V1__init.sql | 1952043475 | root         | 2018-03-06 11:25:58 |             16 |       1 |
+----------------+---------+-------------+------+--------------+------------+--------------+---------------------+----------------+---------+
1 row in set (0.00 sec)

它存储当前迁移的版本、脚本文件名和校验和以及表中的其他详细信息。

当您运行应用程序时,Flyway 首先通过计算它们的校验和并将其与存储在元数据表中的校验和匹配来验证已应用的迁移脚本。

因此,如果在应用迁移后更改 V1__init.sql,Flyway 将抛出一个错误,指出校验和不匹配。

因此,要对架构进行任何更改,您需要使用新版本 V2__<NAME>.sql 创建另一个迁移脚本文件,并在运行应用程序时让 Flyway 应用该文件。

添加多个迁移

我们再创建一个迁移脚本,看看flyway是如何自动将数据库迁移到新版本的。

src/main/resources/db/migration 中创建一个新的脚本 V2__testdata.sql,内容如下:

INSERT INTO users(username, first_name, last_name) VALUES('callicoder', 'Rajeev', 'Singh');
INSERT INTO users(username, first_name, last_name) VALUES('flywaytest', 'Flyway', 'Test');

如果你现在运行应用,flyway 会检测到新的迁移脚本,并将数据库迁移到这个版本。

打开 mysql 并检查 users 表。你会看到上面两个条目是在 users 表中自动创建的——

mysql> select * from users;
+----+------------+-----------+------------+
| id | first_name | last_name | username   |
+----+------------+-----------+------------+
|  4 | Rajeev     | Singh     | callicoder |
|  5 | Flyway     | Test      | flywaytest |
+----+------------+-----------+------------+
2 rows in set (0.01 sec)

此外,Flyway 将这个新模式版本存储在其元数据表中 -

mysql> select * from flyway_schema_history;
+----------------+---------+-------------+------+------------------+-------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description | type | script           | checksum    | installed_by | installed_on        | execution_time | success |
+----------------+---------+-------------+------+------------------+-------------+--------------+---------------------+----------------+---------+
|              1 | 1       | init        | SQL  | V1__init.sql     |  1952043475 | root         | 2018-03-06 11:25:58 |             16 |       1 |
|              2 | 2       | testdata    | SQL  | V2__testdata.sql | -1926058189 | root         | 2018-03-06 11:25:58 |              6 |       1 |
+----------------+---------+-------------+------+------------------+-------------+--------------+---------------------+----------------+---------+
2 rows in set (0.00 sec)

相关文章