【jOOQ中文】3. 數據庫版本管理工具Flyway

在執行數據庫遷移時,咱們推薦使用jOOQ與Flyway - 數據庫遷移輕鬆。 在本章中,咱們將簡單的來使用這兩個框架。java

1、Flyway簡介

圖片描述

什麼是Flyway

Flyway是獨立於數據庫的應用、管理、跟蹤數據庫變動的數據庫版本管理工具。
Flyway的項目主頁是:https://flywaydb.org/mysql

爲何使用Flyway

  • 不一樣的開發人員在開發產品特性時,都有可能更新數據庫(添加新表,新的約束等)。當開發人員完成工做並提交代碼時,代碼會被合併到主分支並在測試服務器上執行單元測試與集成測試。咱們在哪一個環節來執行數據庫的更新操做呢?由QA 部門手工執行sql 腳本?或者咱們開發一斷程序自動執行數據庫更新?以什麼順序來執行這些更新腳本?這些問題一樣存在於生產環境。git

  • 咱們的產品部署在不一樣的客戶服務器上,以及不少的測試、聯調、實驗局、銷售環境上。不一樣的客戶和測試環境上都部署着不一樣版本的產品。當他們須要升級他們的產品到新的版本時,咱們不只須要讓他們的管理員能夠升級產品到新的版本,同時須要保留他們的已有數據。在升級產品的步驟中,咱們清楚地知道客戶數據庫的當前版本,以及須要在該數據庫上執行哪些數據庫更新腳本,來更新數據庫表結構與數據庫中已存在的數據。當升級完成時,數據庫表結構及數據應當與升級後的產品版本保持一致。sql

  • 當升級失敗時(好比在升級過程當中出現網絡鏈接失敗),咱們應當支持對失敗進行修復。shell

更多Flyway文章(參考如下文檔)

2、Maven配置Flyway和jOOQ插件

properties

<!-- 數據庫信息 -->
<db.url>jdbc:mysql://127.0.0.1:33006/flyway_test?useUnicode=true&amp;characterEncoding=UTF-8</db.url>
<db.username>root</db.username>
<db.password>123456</db.password>

plugins

<!-- Flyway插件 -->
<plugin>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <version>3.0</version>
    <!-- 在代碼生成時候執行Flyway插件 -->
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <goals>
                <goal>migrate</goal>
            </goals>
        </execution>
    </executions>
    <!-- 指定Flyway遷移腳本文件目錄 -->
    <configuration>
        <url>${db.url}</url>
        <user>${db.username}</user>
        <password>${db.password}</password>
        <locations>
            <location>filesystem:src/main/resources/db/migration</location>
        </locations>
    </configuration>
</plugin>

<!-- jOOQ代碼生成插件 -->
<plugin>
    <groupId>org.jooq</groupId>
    <artifactId>jooq-codegen-maven</artifactId>
    <version>${jooq.version}</version>
    <executions>
        <execution>
            <id>java-generator</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <jdbc>
                    <url>${db.url}</url>
                    <user>${db.username}</user>
                    <password>${db.password}</password>
                </jdbc>
                <generator>
                    <database>
                        <name>org.jooq.util.mysql.MySQLDatabase</name>
                        <includes>.*</includes>
                        <inputSchema>flyway_test</inputSchema>
                    </database>
                    <target>
                        <packageName>test.generated</packageName>
                        <directory>target/generated-sources/jooq-mysql-java</directory>
                    </target>
                </generator>
            </configuration>
        </execution>
    </executions>
</plugin>

3、數據庫增量腳本

假設已經插件MySQL數據庫:flyway_test框架

src/main/resources/db/migration目錄(Flyway插件指定的location目錄)下插件建立腳本文件:maven

  • V1__create_author.sql

  • V2__create_book.sql

這三個腳本按照版本V[1,2,3...]建立,這是腳本的內容:

# V1__create_author.sql
CREATE TABLE `author` (
  `id` int NOT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
INSERT INTO author VALUES (1, 'George', 'Orwell');
INSERT INTO author VALUES (2, 'Paulo', 'Coelho');
# V2__create_book.sql
CREATE TABLE `book` (
  `id` int NOT NULL,
  `author_id` int NOT NULL,
  `title` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
);
INSERT INTO book VALUES (1, 1, '1984');
INSERT INTO book VALUES (2, 1, 'Animal Farm');
INSERT INTO book VALUES (3, 2, 'O Alquimista');
INSERT INTO book VALUES (4, 2, 'Brida');

4、數據庫遷移 & jOOQ代碼生成

執行Maven構建代碼時候,上一步的V1/V2腳本Flyway會按照版本順序去執行,並由jOOQ生成Java代碼:

mvn clean install

成功後,新建測試用例測試:

import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;

import java.sql.Connection;
import java.sql.DriverManager;

import static test.generated.tables.Author.AUTHOR;

/**
 * 測試類
 */
public class Main {
    public static void main(String[] args) {
        // 用戶名
        String userName = "root";
        // 密碼
        String password = "123456";
        // mysql鏈接url
        String url = "jdbc:mysql://127.0.0.1:33006/flyway_test?useUnicode=true&characterEncoding=UTF-8";

        // Connection is the only JDBC resource that we need
        // PreparedStatement and ResultSet are handled by jOOQ, internally
        try (Connection conn = DriverManager.getConnection(url, userName, password)) {
            DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
            Result<Record> result = create.select().from(AUTHOR).fetch();

            for (Record r : result) {
                Integer id = r.getValue(AUTHOR.ID);
                String firstName = r.getValue(AUTHOR.FIRST_NAME);
                String lastName = r.getValue(AUTHOR.LAST_NAME);

                /**
                 * 控制檯輸出
                 * ID: 1 first name: George last name: Orwell
                 * ID: 2 first name: Paulo last name: Coelho
                 */
                System.out.println("ID: " + id + " first name: " + firstName + " last name: " + lastName);
            }

            // 關閉鏈接對象
            conn.close();
        }
        // For the sake of this tutorial, let's keep exception handling simple
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5、數據庫變更

近期書庫裏多了中文書籍,須要爲book表添加語言種類字段

src/main/resources/db/migration目錄下新增修改數據庫腳本:

# V3__book_add_language.sql
ALTER TABLE `book` ADD COLUMN `language_id` int(7) DEFAULT '1' NOT NULL;

從新運行Maven構建:

mvn clean install

測試用例:

import org.jooq.DSLContext;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.impl.DSL;

import java.sql.Connection;
import java.sql.DriverManager;

import static test.generated.tables.Author.AUTHOR;
import static test.generated.tables.Book.BOOK;

/**
 * 測試類
 */
public class BookMain {
    public static void main(String[] args) {
        // 用戶名
        String userName = "root";
        // 密碼
        String password = "123456";
        // mysql鏈接url
        String url = "jdbc:mysql://127.0.0.1:33006/flyway_test?useUnicode=true&characterEncoding=UTF-8";

        // Connection is the only JDBC resource that we need
        // PreparedStatement and ResultSet are handled by jOOQ, internally
        try (Connection conn = DriverManager.getConnection(url, userName, password)) {
            DSLContext create = DSL.using(conn, SQLDialect.MYSQL);
            Result<Record> result = create.select().from(BOOK).fetch();

            for (Record r : result) {
                Integer id = r.getValue(BOOK.ID);
                String firstName = r.getValue(BOOK.TITLE);
                Integer languageId = r.getValue(BOOK.LANGUAGE_ID);

                /**
                 * 控制檯輸出
                 * ID: 1 title: 1984 language: 英文
                 * ID: 2 title: Animal Farm language: 英文
                 * ID: 3 title: O Alquimista language: 英文
                 * ID: 4 title: Brida language: 英文
                 */
                System.out.println("ID: " + id + " title: "
                        + firstName + " language: " + (languageId.intValue() == 1 ? "英文" : "中文"));
            }

            // 關閉鏈接對象
            conn.close();
        }
        // For the sake of this tutorial, let's keep exception handling simple
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【jOOQ中文】教程代碼都會放在碼雲,但願多多宣傳給Star(^_−)☆。

相關文章
相關標籤/搜索