javascript
flyway spring_关于使用Flyway在Spring Boot中管理数据更改的建议
flyway spring
介紹 (Introduction)
Database migrations are essential for the development of an application to progress and scale in any meaningful way.
數據庫遷移對于應用程序的開發以任何有意義的方式進行和擴展至關重要。
Among other things, migrations keep changes to the database recorded in version control, automated, stateful 1, and, perhaps most importantly, reproducible.
除此之外,移民最重要的, 可重復的不斷變化記錄在版本控制數據庫, 自動化,狀態 1,或許。
[1]: I’m not sure if stateful is a common term for this. For me, migrations being stateful means that looking at any database, you can tell what ‘state’ the database is in; that is, what migrations have been applied to it so far. Flyway accomplishes this by creating a history table to record all attempted migrations.
[1]:我不確定有狀態是否是通用術語。 對我來說,遷移是有狀態的,意味著查看任何數據庫,您就可以知道數據庫所在的“狀態”。 也就是說,到目前為止已對其應用了哪些遷移。 Flyway通過創建一個歷史記錄表來記錄所有嘗試的遷移來實現此目的。
問題 (The Issue)
Photo by Arthur Yeti on Unsplash照片由Arthur Yeti在Unsplash上拍攝While schema changes are “respected” enough by developers to be put into migrations, data changes are often not that lucky; data changes are more likely to be performed on an ad-hoc basis on individual environments.
盡管開發人員足夠尊重架構更改以進行遷移,但數據更改通常并不那么幸運。 數據更改更有可能在個別環境中臨時執行。
The downsides of such an approach are, in essence, the opposite of the migration approach’s benefits; these data changes are [often] not committed to version control, not part of the automated deployment pipeline, stateless 2, and hard to track and reproduce.
從本質上講,這種方法的缺點與遷移方法的好處相反。 這些數據更改[通常]不致力于版本控制,不屬于自動部署管道的一部分,是無狀態的,并且難以跟蹤和再現。
These disadvantages are especially apparent when such data changes pertain to what’s often referred to as master data; that is, records that the application assumes, depends on, and might not have a graceful way of dealing with their absence. Such data may include user types (user, admin, etc…), content categories, or localization-related records, to name some.
當此類數據更改與通常稱為主數據的內容有關時,這些缺點尤為明顯。 也就是說,應用程序假定的記錄,依賴的記錄以及可能沒有適當的方法來處理它們的缺失。 這些數據可能包括用戶類型(用戶,管理員等),內容類別或與本地化相關的記錄,僅舉幾例。
Data changes are as essential to the end result as the application code or schema changes and, thus, should be treated equally.
數據更改對于最終結果至關重要,就像應用程序代碼或架構更改一樣,因此應同等對待。
[2]: In the sense that looking at the history table of migrations, there’s no way to tell if certain data changes were applied.
[2]:從查看遷移的歷史記錄表的意義上講,無法確定是否應用了某些數據更改。
我們能做什么 (What We Can Do)
A quick workaround could be to commit any data changes done through SQL to a dedicated location in the codebase and apply them manually.
一種快速的解決方法是將通過SQL完成的所有數據更改提交到代碼庫中的專用位置,然后手動應用它們。
While this is not precisely stateful or automatically reproducible, it does help to get such changes into version control and might make tracking and reproducing them a bit more manageable.
盡管這不是精確的有狀態或自動可復制的,但確實有助于將此類更改納入版本控制,并且可能使跟蹤和復制它們變得更易于管理。
But can we do better?
但是,我們可以做得更好嗎?
建議 (The Suggestion)
A cleaner approach would be to treat data changes similar to schema changes; as first-class database migrations. After all, data changes are as essential to the end result as the application code or schema changes and, thus, should be treated equally.
較干凈的方法是將數據更改與架構更改類似地對待。 作為一流的數據庫遷移。 畢竟,數據更改對于最終結果至關重要,就像應用程序代碼或架構更改一樣,因此應同等對待。
In the context of Flyway, this translates into putting data changes in SQL files alongside other migrations, either versioned or repeatable.
在Flyway的上下文中,這意味著將數據更改與其他遷移( 版本化或可重復的)一起放入SQL文件中。
Photo by William Rouse on Unsplash 威廉·羅斯 ( William Rouse)在Unsplash上拍攝Flyway遷移速成課程 (A Crash Course on Flyway Migrations)
In Flyway, a versioned migration is one that 1- starts with a V, 2- gets applied once, and 3- cannot be modified after it’s been applied. This type is the most common and is often used for schema migrations.
在Flyway中, 版本化遷移是這樣的遷移:1從V開始,2被應用一次,3被應用后不能修改。 此類型是最常見的類型,通常用于架構遷移。
A repeatable migration, on the other hand, is one that 1- starts with an R, 2- may be applied multiple times, and 3- can be modified after it’s been applied. This type is less know and is suggested for creating views, procedures, functions, etc.
另一方面, 可重復的遷移是這樣的遷移:1以R開頭,2可以被多次應用,3可以在應用后被修改。 這種類型鮮為人知,建議用于創建視圖,過程,函數等。
The challenge with repeatable migrations is writing the SQL code. Code in such migrations should be safe to rerun multiple times without producing unintended side effects such as erroring or duplicating records.
可重復遷移的挑戰在于編寫SQL代碼。 這樣的遷移中的代碼應可以安全地重新運行多次,而不會產生意外的副作用,例如錯誤記錄或重復記錄。
共享數據遷移的選擇 (The Choice for Shared Data Migrations)
For shared data migrations across all environments, the choice is largely practical and personal.
對于跨所有環境的共享數據遷移,選擇主要是實際和個人的。
Writing versioned migrations means that your master data is potentially going to be split across multiple files with schema migration files in between. It does free you from having to write repeatable code, though.
編寫版本化的遷移意味著您的主數據可能會被拆分成多個文件,而架構遷移文件將介于兩個文件之間。 但是,它使您不必編寫可重復的代碼。
On the other hand, writing repeatable migrations means that your master data can all sit in one file or a number of data files. It also means that data changes stay out of the way of, and are quite distinguishable from, schema changes. However, it does require you to write repeatable code (which for insert statements is quite manageable as we’ll see later for MySQL at least).
另一方面,編寫可重復的遷移意味著您的主數據可以全部放在一個文件或多個數據文件中。 這也意味著數據更改不影響模式更改,并且與模式更改完全不同。 但是,它確實需要您編寫可重復的代碼(對于插入語句,這是相當可管理的,至少我們稍后將在MySQL上看到)。
針對特定環境的數據遷移的選擇 (The Choice for Environment-specific Data Migrations)
For data migrations that should only be applied to a specific environment (think test data for a test environment or dummy login credentials for dev), the same tradeoffs between versioned and repeatable migrations apply. However, versioned migrations have one more disadvantage in this case; environments other than the one receiving the versioned migration will seem to have “skipped” some versions.
對于僅應應用于特定環境的數據遷移(對于測試環境考慮測試數據,對于開發人員則考慮虛擬登錄憑據),在版本化遷移和可重復遷移之間應用相同的權衡。 但是,在這種情況下,版本化遷移還有另一個缺點。 除了接受版本化遷移的環境以外,其他環境似乎已經“跳過”了某些版本。
Photo on foter.com foter.com上的照片我的建議 (My Suggestion)
If I haven’t already given it away, I prefer repeatable migrations for all data changes to keep them visibly different, maintain continuous versioning for schema changes across all environments, and keep things consistent for both shared and environment-specific data migrations.
如果我還沒有放棄的話,我希望對所有數據更改進行可重復的遷移,以使它們在視覺上保持不同,為所有環境中的架構更改保持連續的版本控制,并使共享數據和特定于環境的數據遷移保持一致。
細節 (The Details)
The specifics of how to, exactly, accomplish this suggestion for three environments; dev, staging, and prod in Spring Boot 2.x can be summarized as:
如何針對三種環境準確實現此建議的細節; Spring Boot 2.x中的 dev , staging和prod可以總結為:
1- Create the following properties files:* application.properties* application-non-prod.properties* application-dev.properties* application-staging.properties* application-prod.properties
1-創建以下屬性文件: * application.properties * application-non-prod.properties * application-dev.properties * application-staging.properties * application-prod.properties
2- Create the following directories at the classpath. In Spring Boot as you’re probably aware, anything under /src/main/resources is added to the classpath:* db/migration/shared* db/migration/non-prod* db/migration/dev* db/migration/staging* db/migration/prod
2-在類路徑下創建以下目錄 。 如您所知,在Spring Boot中, /src/main/resources都添加到類路徑中: * db / migration / shared * db / migration / non-prod * db / migration / dev * db / migration / staging * db /遷移/產品
3- In the properties file for each environment, override the spring.flyway.locations property, which accepts a comma-separated list of locations. In Spring Boot, the default location is db/migration.
3-在每個環境的屬性文件中,覆蓋spring.flyway.locations屬性,該屬性接受以逗號分隔的位置列表。 在Spring Boot中,默認位置是db/migration 。
We want to modify the migrations locations in such a way that:dev reads migrations from the shared, non-prod, and dev directories.staging reads migrations from the shared, non-prod, and staging directories.prod reads migrations from the shared, and prod directories only.
我們希望以以下方式修改遷移位置: dev從shared , non-prod和dev目錄中讀取遷移。 staging從shared , non-prod和暫存目錄讀取遷移。 prod僅從shared和prod目錄讀取遷移。
This can be accomplished by setting the locations property as follows:
可以通過如下設置locations屬性來實現:
* In application-dev.properties, set:
*在application-dev.properties ,設置:
spring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/non-prod,classpath:/db/migration/dev* In application-staging.properties , set:
*在application-staging.properties ,設置:
spring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/non-prod,classpath:/db/migration/staging* In application-prod.properties , set:
*在application-prod.properties ,設置:
spring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/prod4- For any database change, follow these conventions:* Is it a schema change? Create a versioned migration in the shared directory.* Is it a master data change? Create a repeatable migration or update an existing one in the shared directory.* Is it a data change that shouldn’t make its way to production but is ok on other environments? Create a repeatable migration or update an existing one in the non-prod directory.* Is it a data change specific to the dev, staging, or prod environment? Create a repeatable migration or update an existing one in the dev, staging, or prod directory, respectively.
4-對于任何數據庫更改,請遵循以下約定:*是架構更改嗎? 在共享目錄中創建版本化的遷移。*是主數據更改嗎? 創建可重復的遷移或更新共享目錄中的現有遷移。*這是不應該用于生產但在其他環境中還可以的數據更改嗎? 創建可重復的遷移或更新非生產目錄中的現有遷移。*這是特定于dev , staging或prod環境的數據更改嗎? 在dev , staging或prod目錄中分別創建可重復的遷移或更新現有的遷移。
Photo on foter.com foter.com上的照片一個示例實現 (An Example Implementation)
To create a minimal application to test this setup, we can start with an empty Spring Boot project with at least the following dependencies; spring-boot-starter-web, spring-boot-starter-data-jpa, flyway-core, and mysql-connector-java and walk through the following steps 3:
為了創建一個最小的應用程序來測試該設置,我們可以從一個空的Spring Boot項目開始,該項目至少具有以下依賴性: spring-boot-starter-web , spring-boot-starter-data-jpa , flyway-core和mysql-connector-java并完成以下步驟3:
1- Make sure you have a MySQL server running locally on the default port 3306 with a username of root and no password or change values across this tutorial according to your individual setup.
1-確保您的MySQL服務器在默認端口3306上本地運行,用戶名root ,沒有密碼,或者根據您的個人設置在本教程中更改值。
1.1- Access the MySQL server:
1.1-訪問MySQL服務器:
mysql -u root1.2- Then create the dev, staging, and prod databases with:
1.2-然后使用以下命令創建dev , staging和prod數據庫:
CREATE DATABASE managing_flyway_migrations_dev;CREATE DATABASE managing_flyway_migrations_staging;
CREATE DATABASE managing_flyway_migrations_prod;
2- Create properties files under /src/main/resources.2.1- Create a file called application.properties with the following content:
2-在/src/main/resources下創建屬性文件.2.1-創建一個名為application.properties的文件,其內容如下:
spring.jpa.open-in-view=false# Change this value to 1.2 for the Third Run or remove all togetherspring.flyway.target=1.1
2.2- Create an empty file called application-non-prod.properties .3
2.2-創建一個名為application-non-prod.properties的空文件。
2.3- Create a file called application-dev.properties with the following content:
2.3-創建一個名為application-dev.properties的文件,其內容如下:
spring.profiles.include=non-prodserver.port=8081spring.datasource.url=jdbc:mysql://localhost:3306spring.datasource.username=root
spring.datasource.password=
spring.datasource.name=managing_flyway_migrations_devspring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/non-prod,classpath:/db/migration/dev
spring.flyway.schemas=${spring.datasource.name}
2.4- Create a file called application-staging.properties with the following content:
2.4-創建一個名為application-staging.properties的文件,其內容如下:
spring.profiles.include=non-prodserver.port=8082spring.datasource.url=jdbc:mysql://localhost:3306spring.datasource.username=root
spring.datasource.password=
spring.datasource.name=managing_flyway_migrations_stagingspring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/non-prod,classpath:/db/migration/staging
spring.flyway.schemas=${spring.datasource.name}
2.5- Create a file called application-prod.properties with the following content:
2.5-創建一個名為application-prod.properties的文件,其內容如下:
server.port=8083spring.datasource.url=jdbc:mysql://localhost:3306spring.datasource.username=root
spring.datasource.password=
spring.datasource.name=managing_flyway_migrations_prodspring.flyway.locations=classpath:/db/migration/shared,classpath:/db/migration/prod
spring.flyway.schemas=${spring.datasource.name}
3- Create the migrations files under src/main/resources/db/migration.3.1- Under shared, create a file called V1_1__Initial_Schema.sql with the following content:
3-在src/main/resources/db/migration下創建遷移文件.3.1-在shared ,創建一個名為V1_1__Initial_Schema.sql的文件,其內容如下:
CREATE TABLE roles (id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(100),PRIMARY KEY (id)
);CREATE TABLE users (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255),
role_id BIGINT NOT NULL,PRIMARY KEY (id),FOREIGN KEY (role_id) REFERENCES roles (id)
);CREATE TABLE content_categories (
id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,PRIMARY KEY (id)
);CREATE TABLE content (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(255),
category_id BIGINT NOT NULL,PRIMARY KEY (id),FOREIGN KEY (category_id) REFERENCES content_categories(id)
);
3.2- Under shared, create a file called V1_2__Add_content_topic.sql with the following content:
3.2-在shared ,創建一個名為V1_2__Add_content_topic.sql的文件,其內容如下:
CREATE TABLE content_topics (id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,PRIMARY KEY (id)
);ALTER TABLE content
ADD COLUMN topic_id BIGINT,
ADD CONSTRAINT FOREIGN KEY (topic_id) REFERENCES content_topics(id);
3.3- Under shared, create a file called R__1_Master_Data.sql with the following content:
3.3-在shared ,創建一個名為R__1_Master_Data.sql的文件,其內容如下:
INSERT INTOroles (id, name)
VALUES (1, 'System'), (2, 'Admin'), (3, 'User')
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`);INSERT INTO
content_categories (id, name)
VALUES (1, 'Category 1'), (2, 'Category 2')
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`);# INSERT statements for the First Run
# Comment out for the Third Run
####################################################################
INSERT INTO
content (id, name, category_id)
VALUES (1, 'Content 1.1', 1), (2, 'Content 1.2', 1),
(3, 'Content 2.1', 2), (4, 'Content 2.2', 2)
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`id`), category_id=VALUES(`category_id`);
##################################################################### INSERT statements for the Third Run
# Uncomment for the Third Run
####################################################################
# INSERT INTO
# content_topics (id, name)
# VALUES (1, 'Topic 1'), (2, 'Topic 2')
# ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`);
#
# INSERT INTO
# content (id, name, category_id, topic_id)
# VALUES (1, 'Content 1.1', 1, 1), (2, 'Content 1.2', 1, 2),
# (3, 'Content 2.1', 2, 2), (4, 'Content 2.2', 2, 1)
# ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`), category_id=VALUES(`category_id`), topic_id=VALUES(`topic_id`);
####################################################################
Note: Notice that this migration starts with an R. This is what makes it a repeatable migration.
注意 :請注意,此遷移以R.開頭R.這就是使其成為可重復遷移的原因。
Note 2: Notice that the number in the name of the migration is neither necessary nor does it mean a specific version. I’m using numbers in the description of data migrations simply to order their execution. Flyway executes versioned migrations according to their versions first, then repeatable migrations alphabetically according to their descriptions.
注2 :請注意,遷移名稱中的數字既不是必需的,也不表示特定版本。 我在數據遷移的描述中使用數字只是為了命令執行。 Flyway首先根據其版本執行版本化的遷移,然后根據其描述按字母順序執行可重復的遷移。
3.4- Under non-prod, create a file called R__2_Non_prod_login.sql with the following content:
3.4-在non-prod ,創建一個名為R__2_Non_prod_login.sql的文件,其內容如下:
INSERT INTOusers (id, name, role_id)
VALUES (201, 'SuperAdmin', 1)
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`), role_id=VALUES(`role_id`);
3.5- Under dev, create a file called R__3_Dev_login.sql with the following content:
3.5-在dev之下,創建一個名為R__3_Dev_login.sql的文件,其內容如下:
INSERT INTOusers (id, name, role_id)
VALUES (301, 'Developer 1', 2), (302, 'Developer 2', 2)
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`), role_id=VALUES(`role_id`);
3.6- Under staging, create a file called R__3_Staging_login.sql with the following content:
3.6-在staging ,創建一個名為R__3_Staging_login.sql的文件,其內容如下:
INSERT INTOusers (id, name, role_id)
VALUES (301, 'QA 1', 3), (302, 'QA 2', 3)
ON DUPLICATE KEY UPDATE id=id, name=VALUES(`name`), role_id=VALUES(`role_id`);
By now, we have all the code and configurations we need for our first run.
到現在為止,我們已經擁有了第一次運行所需的所有代碼和配置。
Photo by Fabio Comparelli on Unsplash Fabio Comparelli在Unsplash上拍攝的照片第一次運行 (First Run)
In this first run, we’ll execute the 1.1 versioned migration alongside the other repeated ones to simulate a deployment with the initial database schema and data.
在第一次運行中,我們將與其他重復 版本一起執行1.1 版本的遷移,以模擬具有初始數據庫架構和數據的部署。
The two important locations to differentiate between runs in these tests are the Flyway target in application.properties and the INSERT statements in R__1_Master_Data.sql. If you’re using the accompanying GitHub repository, make sure you’re on the first-run branch.
在這些測試運行之間的區分這兩個重要的位置是在遷飛目標application.properties ,并在INSERT語句R__1_Master_Data.sql 。 如果您使用隨附的GitHub存儲庫,請確保您位于first-run分支。
測試`dev`配置文件 (Testing the `dev` Profile)
Run the application with the dev profile active:
在dev配置文件處于活動狀態的情況下運行應用程序:
mvn spring-boot:run -Dspring.profiles.active=devBy now, we expect a number of things:* The versioned migration V1_1__Initial_Schema.sql was applied.* The versioned migration V1_2__Add_content_topic.sql was not applied (since we have the target set to 1.1).* The shared repeated migration R__1_Master_Data.sql was applied.* The non-prod repeated migration R__2_Non_prod_login.sql was applied.* The dev repeated migration R__3_Dev_login.sql was applied.
到目前為止,我們期望發生以下事情:*應用了版本化的遷移V1_1__Initial_Schema.sql 。*沒有應用版本化的遷移V1_2__Add_content_topic.sql (因為我們將目標設置為1.1 )。*共享的重復遷移R__1_Master_Data.sql是*已應用非產品重復遷移R__2_Non_prod_login.sql 。*已應用dev 重復遷移R__3_Dev_login.sql 。
Use the Dev Database
使用開發數據庫
USE managing_flyway_migrations_dev;Check the History Table
查看歷史記錄表
To verify this, we check the flyway_schema_history that Flyway would’ve created by running the following inside our database server:
為了驗證這一點,我們檢查flyway_schema_history 可以通過在數據庫服務器內部運行以下命令來創建:
SELECT installed_rank, version, description, success FROM flyway_schema_history;The output of the SELECT statement above should look as follows:
上面的SELECT語句的輸出應如下所示:
+----------------+---------+------------------+---------+| installed_rank | version | description | success |
+----------------+---------+------------------+---------+
| 1 | 1.1 | Initial Schema | 1 |
| 2 | NULL | 1 Master Data | 1 |
| 3 | NULL | 2 Non prod login | 1 |
| 4 | NULL | 3 Dev login | 1 |
+----------------+---------+------------------+---------+
Check the Content Table
檢查內容表
The content table should contain the records we inserted in the Master Data as follows:
內容表 應該包含我們插入到主數據中的記錄,如下所示:
SELECT * FROM content;This should output:
這應該輸出:
+----+-------------+-------------+| id | name | category_id |
+----+-------------+-------------+
| 1 | Content 1.1 | 1 |
| 2 | Content 1.2 | 1 |
| 3 | Content 2.1 | 2 |
| 4 | Content 2.2 | 2 |
+----+-------------+-------------+
Check the Users Table
檢查用戶表
In the users table, we should see records from both the Non-production Login (SuperAdmin) as well as the Dev Login migrations we defined. Run the command:
在用戶表中,我們應該看到非生產登錄 (SuperAdmin)以及我們定義的開發登錄的遷移記錄。 運行命令:
SELECT * FROM users;This should output:
這應該輸出:
+-----+-------------+---------+| id | name | role_id |
+-----+-------------+---------+
| 201 | SuperAdmin | 1 |
| 301 | Developer 1 | 2 |
| 302 | Developer 2 | 2 |
+-----+-------------+---------+
I leave testing the staging profile to the reader as it’s almost identical to the tests described in this section.
我將測試staging配置文件留給讀者,因為它幾乎與本節中描述的測試相同。
Now, let’s move on to testing production!
現在,讓我們繼續測試生產!
測試` prod配置文件 (Testing the `prod` Profile)
Run the application with the prod profile active:
在prod配置文件處于活動狀態的情況下運行應用程序:
mvn spring-boot:run -Dspring.profiles.active=prodBy now, we expect a number of things:* The versioned migration V1_1__Initial_Schema.sql was applied.* The versioned migration V1_2__Add_content_topic.sql was not applied.* The shared repeated migration R__1_Master_Data.sql was applied.
到現在為止,我們期待一些事情:*本版本遷移V1_1__Initial_Schema.sql 。應用*的版本控制的遷移V1_2__Add_content_topic.sql 。不適用*共享重復遷移R__1_Master_Data.sql應用。
Use the Prod Database
使用產品數據庫
USE managing_flyway_migrations_prod;Check the History Table
查看歷史記錄表
To verify this, we check the flyway_schema_history that Flyway would’ve created by running the following inside our database server:
為了驗證這一點,我們檢查flyway_schema_history 可以通過在數據庫服務器內部運行以下命令來創建:
SELECT installed_rank, version, description, success FROM flyway_schema_history;The output of the SELECT statement above should look as follows:
上面的SELECT語句的輸出應如下所示:
+----------------+---------+----------------+---------+| installed_rank | version | description | success |
+----------------+---------+----------------+---------+
| 1 | 1.1 | Initial Schema | 1 |
| 2 | NULL | 1 Master Data | 1 |
+----------------+---------+----------------+---------+
Notice that in production, we don’t have any of the test credentials defined in non-prod, dev, or staging.
請注意,在生產環境中,我們沒有在非生產,開發或暫存中定義的任何測試憑據。
Check the Content Table
檢查內容表
The content table should contain the records we inserted in the Master Data similar to what we saw in dev:
內容表 應該包含我們插入到主數據中的記錄,類似于在dev看到的記錄:
SELECT * FROM content;This should output:
這應該輸出:
+----+-------------+-------------+| id | name | category_id |
+----+-------------+-------------+
| 1 | Content 1.1 | 1 |
| 2 | Content 1.2 | 1 |
| 3 | Content 2.1 | 2 |
| 4 | Content 2.2 | 2 |
+----+-------------+-------------+
Check the Users Table
檢查用戶表
The users table should be empty:
用戶表應為空:
SELECT * FROM users;This should output:
這應該輸出:
Empty set (0.00 sec)Photo by Chander R on Unsplash Chander R在Unsplash上的照片第二次跑 (Second Run)
In this run, we simulate an application restart or a deployment that contains no migration changes. Here, we’re really testing Flyway’s behavior.
在此運行中,我們模擬應用程序重新啟動或不包含任何遷移更改的部署。 在這里,我們正在測試Flyway的行為。
測試`dev`配置文件 (Testing the `dev` Profile)
Stop and rerun the dev application:
停止并重新運行dev應用程序:
mvn spring-boot:run -Dspring.profiles.active=dev測試` prod配置文件 (Testing the `prod` Profile)
Stop and rerun the prod application as well:
也停止并重新運行prod應用程序:
mvn spring-boot:run -Dspring.profiles.active=prod結果 (Results)
In the stream of logs that Spring generates in each run, look for a line containing the following:
在Spring每次運行中生成的日志流中,查找包含以下內容的行:
Schema `managing_flyway_migrations_dev` is up to date. No migration necessary.This tells us that Flyway detected that no changes were made to the migrations, and therefore it took no action. Notice that even repeatable migrations were’s re-applied by Flyway; this is because the files, and therefore their checksums, didn’t change.
這告訴我們Flyway檢測到未對遷??移進行任何更改,因此未采取任何措施。 請注意, Flyway甚至重新應用了可重復的遷移。 這是因為文件及其校驗和沒有發生變化。
Feel free to explore records in the tables after the restart to verify that nothing actually changed before moving on to the Third Run.
重新啟動后,請隨意瀏覽表中的記錄,以確保在進行第三次運行之前沒有任何實際更改。
Andrew Tanglao on 安德魯·唐勞 ( UnsplashUnderlash)第三輪 (Third Run)
Now, let’s simulate a deployment with changes made to both versioned and repeatable migrations.
現在,讓我們模擬對版本化遷移和可重復遷移所做的更改的部署。
In the application.propertiesfile, change the spring.flyway.target property to 1.2 or delete it altogether. This will cause Flyway to apply the second versioned migration we have; V1_2__Add_content_topic.sql.
在application.properties文件中,將spring.flyway.target屬性更改為1.2或將其完全刪除。 這將導致Flyway應用我們擁有的第二個版本化的遷移; V1_2__Add_content_topic.sql 。
In the R__1_Master_Data.sql, comment out the block for the First Run, and uncomment the one for the Third Run, as mentioned. Notice that in an actual application, you’d really be modifying the existing code instead of the commenting stuff.
R__1_Master_Data.sql ,在R__1_Master_Data.sql ,注釋掉“ 第一次運行”的塊,并取消注釋“ 第三次運行”的塊。 注意,在實際的應用程序中,您實際上是在修改現有代碼,而不是注釋內容。
If you’re using the GitHub repository, simply checkout the third-run branch.
如果您使用的是GitHub存儲庫,只需簽出third-run分支。
測試`dev`配置文件 (Testing the `dev` Profile)
Similar to the previous steps, stop and rerun the dev application:
與前面的步驟類似,停止并重新運行dev應用程序:
mvn spring-boot:run -Dspring.profiles.active=devBy now, we expect a number of things:* The versioned migration V1_1__Initial_Schema.sql was not re-applied.* The versioned migration V1_2__Add_content_topic.sql was applied.* The shared repeated migration R__1_Master_Data.sql was re-applied (since it was changed).* The non-prod repeated migration R__2_Non_prod_login.sql was not re-applied (since it was not changed).* The dev repeated migration R__3_Dev_login.sql was not re-applied.
到現在為止,我們期待一些事情:*的版本控制的遷移V1_1__Initial_Schema.sql 。 沒有重新申請*的版本控制的遷移V1_2__Add_content_topic.sql 。應用*共享重復遷移R__1_Master_Data.sql被重新應用(因為它被改變)。* 未重新應用非產品重復遷移R__2_Non_prod_login.sql (因為未更改)。* 未重新應用開發人員重復遷移R__3_Dev_login.sql 。
Use the Dev Database
使用開發數據庫
USE managing_flyway_migrations_dev;Check the History Table
查看歷史記錄表
Similar to the previous tests, run:
與先前的測試類似,運行:
SELECT installed_rank, version, description, success FROM flyway_schema_history;The output of the SELECT statement above should look as follows:
上面的SELECT語句的輸出應如下所示:
+----------------+---------+-------------------+---------+| installed_rank | version | description | success |
+----------------+---------+-------------------+---------+
| 1 | 1.1 | Initial Schema | 1 |
| 2 | NULL | 1 Master Data | 1 |
| 3 | NULL | 2 Non prod login | 1 |
| 4 | NULL | 3 Dev login | 1 |
| 5 | 1.2 | Add content topic | 1 |
| 6 | NULL | 1 Master Data | 1 |
+----------------+---------+-------------------+---------+
Notice the 1.2 versioned migration at the rank 5 as well as the re-application of the modified Master Data migration at 6.
注意排名5的1.2 版本遷移以及重新應用修改后的Master Data遷移6 。
Check the Content Table
檢查內容表
The content table should contain the records we inserted in the modified Master Data, including the new topic_id column introduced by the new migrations:
內容表 應包含我們在修改后的主數據中插入的記錄,包括新遷移引入的新topic_id列:
SELECT * FROM content;This should output:
這應該輸出:
+----+-------------+-------------+----------+| id | name | category_id | topic_id |
+----+-------------+-------------+----------+
| 1 | Content 1.1 | 1 | 1 |
| 2 | Content 1.2 | 1 | 2 |
| 3 | Content 2.1 | 2 | 2 |
| 4 | Content 2.2 | 2 | 1 |
+----+-------------+-------------+----------+
Check the Users Table
檢查用戶表
The users table wouldn’t have changed since the last run:
自上次運行以來, users表不會更改:
SELECT * FROM users;This should output:
這應該輸出:
+-----+-------------+---------+| id | name | role_id |
+-----+-------------+---------+
| 201 | SuperAdmin | 1 |
| 301 | Developer 1 | 2 |
| 302 | Developer 2 | 2 |
+-----+-------------+---------+
測試` prod配置文件 (Testing the `prod` Profile)
Similarly, stop and rerun the prod application:
同樣,停止并重新運行prod應用程序:
mvn spring-boot:run -Dspring.profiles.active=prodBy now, we expect the following:* The versioned migration V1_1__Initial_Schema.sql was not re-applied.* The versioned migration V1_2__Add_content_topic.sql was applied.* The shared repeated migration R__1_Master_Data.sql was re-applied.
到現在為止,我們預計如下:*的版本控制的遷移V1_1__Initial_Schema.sql 沒有再次應用*的版本控制的遷移。 V1_2__Add_content_topic.sql應用*共享重復遷移。 R__1_Master_Data.sql被重施。
Use the Prod Database
使用產品數據庫
USE managing_flyway_migrations_prod;Check the History Table
查看歷史記錄表
Two new records should show in the flyway_schema_historytable:
兩個新記錄應顯示在flyway_schema_history表中:
SELECT installed_rank, version, description, success FROM flyway_schema_history;The output of the SELECT statement above should look as follows:
上面的SELECT語句的輸出應如下所示:
+----------------+---------+-------------------+---------+| installed_rank | version | description | success |
+----------------+---------+-------------------+---------+
| 1 | 1.1 | Initial Schema | 1 |
| 2 | NULL | 1 Master Data | 1 |
| 3 | 1.2 | Add content topic | 1 |
| 4 | NULL | 1 Master Data | 1 |
+----------------+---------+-------------------+---------+
Check the Content Table
檢查內容表
Similar to dev, the content records should contain the new topic_id column:
與dev類似, 內容記錄應包含新的topic_id列:
SELECT * FROM content;This should output:
這應該輸出:
+----+-------------+-------------+----------+| id | name | category_id | topic_id |
+----+-------------+-------------+----------+
| 1 | Content 1.1 | 1 | 1 |
| 2 | Content 1.2 | 1 | 2 |
| 3 | Content 2.1 | 2 | 2 |
| 4 | Content 2.2 | 2 | 1 |
+----+-------------+-------------+----------+
Check the Users Table
檢查用戶表
The users table should still be empty:
用戶表仍應為空:
SELECT * FROM users;This should output:
這應該輸出:
Empty set (0.00 sec)Photo by Aw Creative on Unsplash圖片由Aw Creative在Unsplash上拍攝干凈運行 (Clean Run)
Finally, let’s simulate a fresh installation of the application at this stage. This simulates how migrations would work in a fresh environment with an empty database or when the project is freshly set up on a new local development machine.
最后,讓我們在此階段模擬該應用程序的全新安裝。 這模擬了遷移如何在具有空數據庫的新環境中工作,或者何時在新的本地開發計算機上新設置了項目。
Let’s use the staging environment here for a change. We’ll pretend that we’re just now setting up staging with the current code and a fresh database:
讓我們在這里使用staging環境進行更改。 我們假裝我們現在正在使用當前代碼和一個新數據庫來設置staging :
DROP DATABASE managing_flyway_migrations_staging;CREATE DATABASE managing_flyway_migrations_staging;
Now run the staging application:
現在運行staging應用程序:
mvn spring-boot:run -Dspring.profiles.active=stagingBy this, we expect the following:* The versioned migration V1_1__Initial_Schema.sql was applied.* The versioned migration V1_2__Add_content_topic.sql was applied.* The shared repeated migration R__1_Master_Data.sql was applied.* The non-prod repeated migration R__2_Non_prod_login.sql was applied.* The staging repeated migration R__3_Staging_login.sql was applied.
這樣,我們期望滿足以下條件:*應用了版本化的遷移V1_1__Initial_Schema.sql 。*應用了版本化的遷移V1_2__Add_content_topic.sql 。*應用了共享的 重復遷移R__1_Master_Data.sql 。* 非產品 重復遷移R__2_Non_prod_login.sql被應用了。 *已應用分段 重復遷移R__3_Staging_login.sql 。
Use the Staging Database
使用登臺數據庫
USE managing_flyway_migrations_staging;Check the History Table
查看歷史記錄表
Two new records should show in the flyway_schema_historytable:
兩個新記錄應顯示在flyway_schema_history表中:
SELECT installed_rank, version, description, success FROM flyway_schema_history;The output of the SELECT statement above should look as follows:
上面的SELECT語句的輸出應如下所示:
+----------------+---------+-------------------+---------+| installed_rank | version | description | success |
+----------------+---------+-------------------+---------+
| 1 | 1.1 | Initial Schema | 1 |
| 2 | 1.2 | Add content topic | 1 |
| 3 | NULL | 1 Master Data | 1 |
| 4 | NULL | 2 Non prod login | 1 |
| 5 | NULL | 3 Staging login | 1 |
+----------------+---------+-------------------+---------+
Note: Notice that the Master Data migration is applied once. Also, notice that this works fine because repeated migrations are always run after all versioned migrations have been applied.
注意 :請注意, 主數據遷移僅應用一次。 此外,請注意,此方法的效果很好,因為在應用 所有 版本化的遷移后始終會重復運行遷移。
Check the Content Table
檢查內容表
The content table should already have all changes, including the topic_id column:
內容表應該已經進行了所有更改,包括topic_id列:
SELECT * FROM content;This should output:
這應該輸出:
+----+-------------+-------------+----------+| id | name | category_id | topic_id |
+----+-------------+-------------+----------+
| 1 | Content 1.1 | 1 | 1 |
| 2 | Content 1.2 | 1 | 2 |
| 3 | Content 2.1 | 2 | 2 |
| 4 | Content 2.2 | 2 | 1 |
+----+-------------+-------------+----------+
Check the Users Table
檢查用戶表
The users table should have records from both the Non-production Login and Staging Login migrations:
users表應該具有非生產登錄和暫存登錄遷移的記錄:
SELECT * FROM users;This should output:
這應該輸出:
+-----+------------+---------+| id | name | role_id |
+-----+------------+---------+
| 201 | SuperAdmin | 1 |
| 301 | QA 1 | 3 |
| 302 | QA 2 | 3 |
+-----+------------+---------+
代碼 (The Code)
If you’d like a test drive with minimal effort, I’ve put together the same setup handy on GitHub: https://github.com/sayadi/managing-flyway-migrations-spring-boot.
如果您想以最小的努力進行測試,我可以在GitHub上方便地進行相同的設置: https : //github.com/sayadi/managing-flyway-migrations-spring-boot 。
最后的話 (A Final Word)
While this setup works, it is something I dreamt up for this article as a solution to a repeated problem I see. However, we haven’t had a chance to test this on a production application yet.
盡管此設置有效,但我為本文構想的是作為我遇到的重復問題的解決方案。 但是,我們還沒有機會在生產應用程序上對此進行測試。
If you do end up using it in a real setup, do let me know in the comments below what works for you, what doesn’t, and what changes you might have had to do. Thanks for reading!
如果您確實要在實際設置中使用它,請在下面的評論中讓我知道什么對您有用,什么不起作用以及您可能需要進行哪些更改。 謝謝閱讀!
翻譯自: https://levelup.gitconnected.com/a-suggestion-on-managing-data-changes-in-spring-boot-using-flyway-b87cf87f8e88
flyway spring
總結
以上是生活随笔為你收集整理的flyway spring_关于使用Flyway在Spring Boot中管理数据更改的建议的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 破局:技术视野与规划
- 下一篇: 初始化oracle环境失败,Oracle