
При выполнении миграции баз данных мы в Data Geekery рекомендуем использовать jOOQ с Flyway — Миграция баз данных Made Easy . В этом посте мы рассмотрим простой способ начать работу с двумя фреймворками.
философия
Существует множество способов взаимодействия jOOQ и Flyway друг с другом в различных настройках разработки. В этом уроке мы покажем только один вариант такой командной игры фреймворка — вариант, который мы находим особенно привлекательным для большинства случаев использования.
Общая философия и рабочий процесс, лежащий в основе следующего подхода, могут быть обобщены следующим образом:
- 1. Приращение базы данных
- 2. Миграция базы данных
- 3. Повторная генерация кода
- 4. Разработка
Четыре вышеуказанных шага можно повторять снова и снова, каждый раз, когда вам нужно что-то изменить в вашей базе данных. Конкретнее, давайте рассмотрим:
- 1. Приращение базы данных — вам нужен новый столбец в вашей базе данных, поэтому вы пишете необходимый DDL в скрипте Flyway
- 2. Перенос базы данных. Этот сценарий Flyway теперь является частью вашего конечного результата, которым вы можете поделиться со всеми разработчиками, которые могут перенести свои базы данных вместе с ним, при следующей проверке ваших изменений
- 3. Повторная генерация кода — после переноса базы данных вы регенерируете все артефакты jOOQ (см. Генерацию кода ) локально
- 4. Разработка. Вы продолжаете разрабатывать свою бизнес-логику, писать код для обновленной схемы базы данных.
0,1. Конфигурация проекта Maven — Свойства
Следующие свойства определены в нашем pom.xml, чтобы можно было повторно использовать их между конфигурациями плагинов:
|
1
2
3
4
|
<properties> <db.url>jdbc:h2:~/flyway-test</db.url> <db.username>sa</db.username></properties> |
0.2. Конфигурация проекта Maven — Зависимости
Хотя jOOQ и Flyway можно использовать в автономных сценариях миграции, в этом руководстве мы будем использовать Maven для стандартной настройки проекта. Вы также найдете исходный код этого руководства на GitHub и полный файл pom.xml здесь .
Это зависимости, которые мы используем в нашей конфигурации Maven:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<!-- We'll add the latest version of jOOQ and our JDBC driver - in this case H2 --><dependency> <groupId>org.jooq</groupId> <artifactId>jooq</artifactId> <version>3.4.0</version></dependency><dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.177</version></dependency><!-- For improved logging, we'll be using log4j via slf4j to see what's going on during migration and code generation --><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version></dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version></dependency><!-- To esnure our code is working, we're using JUnit --><dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope></dependency> |
0,3. Конфигурация проекта Maven — Плагины
После зависимостей давайте просто добавим плагины Flyway и jOOQ Maven следующим образом. Плагин Flyway:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<plugin> <groupId>org.flywaydb</groupId> <artifactId>flyway-maven-plugin</artifactId> <version>3.0</version> <!-- Note that we're executing the Flyway plugin in the "generate-sources" phase --> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>migrate</goal> </goals> </execution> </executions> <!-- Note that we need to prefix the db/migration path with filesystem: to prevent Flyway from looking for our migration scripts only on the classpath --> <configuration> <url>${db.url}</url> <user>${db.username}</user> <locations> <location>filesystem:src/main/resources/db/migration</location> </locations> </configuration></plugin> |
Приведенная выше конфигурация плагина Flyway Maven будет считывать и выполнять все сценарии миграции базы данных из src/main/resources/db/migration до компиляции исходного кода Java. В то время как официальная документация по Flyway предполагает, что миграции должны выполняться на этапе compile , генератор кода jOOQ полагается на то, что такие миграции выполнялись до генерации кода.
После плагина Flyway мы добавим плагин jOOQ Maven. Для более подробной информации, пожалуйста, обратитесь к разделу руководства о конфигурации генерации кода .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<plugin> <groupId>org.jooq</groupId> <artifactId>jooq-codegen-maven</artifactId> <version>${org.jooq.version}</version> <!-- The jOOQ code generation plugin is also executed in the generate-sources phase, prior to compilation --> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>generate</goal> </goals> </execution> </executions> <!-- This is a minimal working configuration. See the manual's section about the code generator for more details --> <configuration> <jdbc> <url>${db.url}</url> <user>${db.username}</user> </jdbc> <generator> <database> <includes>.*</includes> <inputSchema>FLYWAY_TEST</inputSchema> </database> <target> <packageName>org.jooq.example.flyway.db.h2</packageName> <directory>target/generated-sources/jooq-h2</directory> </target> </generator> </configuration></plugin> |
Эта конфигурация теперь будет считывать схему FLYWAY_TEST и FLYWAY_TEST в FLYWAY_TEST target/generated-sources/jooq-h2 , а внутри него — в пакет org.jooq.example.flyway.db.h2 .
1. Приращение базы данных
Теперь, когда мы начинаем разработку нашей базы данных. Для этого мы создадим сценарии приращения базы данных, которые мы поместим в каталог src/main/resources/db/migration , как ранее было настроено для плагина Flyway. Мы добавим эти файлы:
- V1__initialise_database.sql
- V2__create_author_table.sql
- V3__create_book_table_and_records.sql
Эти три сценария моделируют нашу схему версий 1-3 (обратите внимание на заглавную V!). Вот содержимое скриптов
|
1
2
3
4
|
-- V1__initialise_database.sqlDROP SCHEMA flyway_test IF EXISTS;CREATE SCHEMA flyway_test; |
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
-- V2__create_author_table.sqlCREATE SEQUENCE flyway_test.s_author_id START WITH 1;CREATE TABLE flyway_test.author ( id INT NOT NULL, first_name VARCHAR(50), last_name VARCHAR(50) NOT NULL, date_of_birth DATE, year_of_birth INT, address VARCHAR(50), CONSTRAINT pk_t_author PRIMARY KEY (ID)); |
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
-- V3__create_book_table_and_records.sqlCREATE TABLE flyway_test.book ( id INT NOT NULL, author_id INT NOT NULL, title VARCHAR(400) NOT NULL, CONSTRAINT pk_t_book PRIMARY KEY (id), CONSTRAINT fk_t_book_author_id FOREIGN KEY (author_id) REFERENCES flyway_test.author(id));INSERT INTO flyway_test.author VALUES (next value for flyway_test.s_author_id, 'George', 'Orwell', '1903-06-25', 1903, null);INSERT INTO flyway_test.author VALUES (next value for flyway_test.s_author_id, 'Paulo', 'Coelho', '1947-08-24', 1947, null);INSERT INTO flyway_test.book VALUES (1, 1, '1984');INSERT INTO flyway_test.book VALUES (2, 1, 'Animal Farm');INSERT INTO flyway_test.book VALUES (3, 2, 'O Alquimista');INSERT INTO flyway_test.book VALUES (4, 2, 'Brida'); |
2. Миграция базы данных и 3. Восстановление кода
Три вышеупомянутых скрипта подобраны Flyway и выполнены в порядке версий. Это можно увидеть очень просто, выполнив:
|
1
|
mvn clean install |
А затем, наблюдая за выходом журнала из Flyway…
|
1
2
3
4
5
6
7
8
9
|
[INFO] --- flyway-maven-plugin:3.0:migrate (default) @ jooq-flyway-example ---[INFO] Database: jdbc:h2:~/flyway-test (H2 1.4)[INFO] Validated 3 migrations (execution time 00:00.004s)[INFO] Creating Metadata table: "PUBLIC"."schema_version"[INFO] Current version of schema "PUBLIC": <>[INFO] Migrating schema "PUBLIC" to version 1[INFO] Migrating schema "PUBLIC" to version 2[INFO] Migrating schema "PUBLIC" to version 3[INFO] Successfully applied 3 migrations to schema "PUBLIC" (execution time 00:00.073s). |
… и из jOOQ на консоли:
|
1
2
3
4
5
6
7
8
|
[INFO] --- jooq-codegen-maven:3.5.0-SNAPSHOT:generate (default) @ jooq-flyway-example ---[INFO] Using this configuration:...[INFO] Generating schemata : Total: 1[INFO] Generating schema : FlywayTest.java[INFO] ----------------------------------------------------------[....][INFO] GENERATION FINISHED! : Total: 337.576ms, +4.299ms |
4. Разработка
Обратите внимание, что все предыдущие шаги выполняются автоматически, каждый раз, когда кто-то добавляет новые скрипты миграции в модуль Maven. Например, участник команды мог зафиксировать новый сценарий миграции, проверить его, перестроить и получить последние сгенерированные jOOQ источники для своей собственной базы данных разработки или тестирования интеграции.
Теперь, когда эти шаги выполнены, вы можете приступить к написанию запросов к базе данных. Представьте себе следующий тест
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import org.jooq.Result;import org.jooq.impl.DSL;import org.junit.Test;import java.sql.DriverManager;import static java.util.Arrays.asList;import static org.jooq.example.flyway.db.h2.Tables.*;import static org.junit.Assert.assertEquals;public class AfterMigrationTest { @Test public void testQueryingAfterMigration() throws Exception { try (Connection c = DriverManager.getConnection("jdbc:h2:~/flyway-test", "sa", "")) { Result<?> result = DSL.using(c) .select( AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, BOOK.ID, BOOK.TITLE ) .from(AUTHOR) .join(BOOK) .on(AUTHOR.ID.eq(BOOK.AUTHOR_ID)) .orderBy(BOOK.ID.asc()) .fetch(); assertEquals(4, result.size()); assertEquals(asList(1, 2, 3, 4), result.getValues(BOOK.ID)); } }} |
Если вы снова запустите mvn clean install , вышеприведенный тест интеграции будет скомпилирован и пройден!
Подтверждают
Сила этого подхода становится очевидной, как только вы начнете выполнять модификации базы данных таким способом Давайте предположим, что французский парень в нашей команде предпочитает, чтобы все было по-своему (без обид)
|
1
2
3
|
-- V4__le_french.sqlALTER TABLE flyway_test.book ALTER COLUMN title RENAME TO le_titre; |
Они проверяют это, вы проверяете новый скрипт миграции базы данных, запускаете
|
1
|
mvn clean install |
А затем просмотрите вывод журнала:
|
1
2
3
4
5
6
7
|
[INFO] --- flyway-maven-plugin:3.0:migrate (default) @ jooq-flyway-example ---[INFO] --- flyway-maven-plugin:3.0:migrate (default) @ jooq-flyway-example ---[INFO] Database: jdbc:h2:~/flyway-test (H2 1.4)[INFO] Validated 4 migrations (execution time 00:00.005s)[INFO] Current version of schema "PUBLIC": 3[INFO] Migrating schema "PUBLIC" to version 4[INFO] Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.016s). |
Пока все хорошо, но позже:
|
1
2
3
4
|
[ERROR] COMPILATION ERROR :[INFO] -------------------------------------------------------------[ERROR] C:\...\AfterMigrationTest.java:[24,19] error: cannot find symbol[INFO] 1 error |
Когда мы вернемся к нашему тесту интеграции Java, мы сразу увидим, что на столбец TITLE все еще ссылаются, но он больше не существует:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class AfterMigrationTest { @Test public void testQueryingAfterMigration() throws Exception { try (Connection c = DriverManager.getConnection("jdbc:h2:~/flyway-test", "sa", "")) { Result<?> result = DSL.using(c) .select( AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, BOOK.ID, BOOK.TITLE // ^^^^^ This column no longer exists. // We'll have to rename it to LE_TITRE ) .from(AUTHOR) .join(BOOK) .on(AUTHOR.ID.eq(BOOK.AUTHOR_ID)) .orderBy(BOOK.ID.asc()) .fetch(); assertEquals(4, result.size()); assertEquals(asList(1, 2, 3, 4), result.getValues(BOOK.ID)); } }} |
Вывод
Это руководство очень просто показывает, как вы можете построить надежный процесс разработки с использованием Flyway и jOOQ для предотвращения ошибок, связанных с SQL, на самых ранних этапах жизненного цикла разработки — сразу во время компиляции, а не в процессе производства!
| Ссылка: | Flyway и jOOQ для непревзойденной производительности SQL от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ . |
