JavaRush /Java блог /Random UA /Додаємо все, що пов'язане із БД. (Частина 1) - "Java-прое...
Roman Beekeeper
35 рівень

Додаємо все, що пов'язане із БД. (Частина 1) - "Java-проект від А до Я"

Стаття з групи Random UA
Крок за кроком ми йдемо до нашої мети. "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 1Сьогодні нам потрібно вирішити виконати багато завдань:
  1. Додати Flyway. Тут же налаштуємо розгортання БД для проекту.
  2. Додати схему БД.
  3. Додати шар репозиторію.
  4. Додати команду статистики бота.
  5. Написати тести, зрештою.
Тому сідайте зручніше: буде лонгрід. Ми вже навчабося деплоїти наш додаток за допомогою docker та docker-compose. Це було нелегко, і тих, у кого це вдалося зробити, вітаю. Якщо будуть якісь питання щодо реалізації - можете подивитися на код у цьому пулл-реквесті .

Додаємо Flyway

Щоб додати Flyway, потрібно мати базу даних, яку ми додамо як ще один сервіс у docker-compose. Минулого разу я говорив, що в docker-compose є секція services, яка якраз і відповідає за додавання та управління якоюсь інфраструктурою — тобто набором додатків/баз даних/месенджерів тощо.
Я вже говорив про те, що таке Flyway і як його додати до SpringBoot додаток . Раджу освіжити інформацію у пам'яті перед прочитанням цієї статті. Також можна почитати README.md файл проекту з демонстрацією статті про Flyway+SpringBoot.
Перше, що ми робимо – оновлюємо нашу main гілку в проекті (git pull) і створюємо нову з назвою нашого завдання – STEP_5_JRTB-1 (git checkout -b STEP_5_JRTB-1). Нагадаю: ми перейменували гілки, щоб відсортувати послідовність виконання завдань у проекті можна було лише за назвою. Це дозволить швидко переходити від одного кроку до іншого. Наразі можна спокійно працювати. Нам потрібно додати три залежності:
<dependency>
  <groupId>org.flywaydb</groupId>
  <artifactId>flyway-core</artifactId>
</dependency>

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <scope>runtime</scope>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Перша залежність відповідає за додавання до проекту FlyWay, друга додає нам можливість підключатися до MySQL бд. Третя – SpringBoot starter, який запускає всю магію використання БД у Spring. І ще додамо ломбок, щоб не писати гетери та сеттери:
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>
Тепер нам потрібна база для розробки. Ми будемо створювати її поки що ( поки я краще не придумав ) як окремий файл docker-compose і окремий файл для application.properties. Є така річ у розробці (і у Spring екосистемі зокрема) як профілі. Залежно від профілю запускаються різні налаштування для роботи. Думаю, у майбутньому ми об'єднаємо docker-compose в один файл і зробимо так, щоб для розробки запускалася лише одна база даних на тих налаштуваннях, які нам потрібні. На даний момент зробимо так:
  1. Створимо файл у корені проекту docker-compose-test.yml, у якому запускатиметься лише база даних із власними налаштуваннями.
  2. Створимо файл application-test.properties з налаштуваннями, які відповідають настройкам у файлі docker-compose-test.yml.
Для роботи з MySQL я взяв офіційний образ з DockerHub : "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 2Швидко перегорнувши, знайшов потрібні змінні: MYSQL_DATABASE - ім'я БД MYSQL_USER - ім'я користувача БД MYSQL_PASSWORD - пароль користувача БД І те, як їх потрібно правильно записати:
jrtb-db:
   image: mysql
   restart: always
   container_name: dev-jrtb-db
   ports:
     - "3306:3306"
   environment:
     MYSQL_DATABASE: "dev_jrtb_db"
     MYSQL_USER: root
     MYSQL_PASSWORD: root
Після цього створюю в корені проекту docker-compose-test.yml:
version: '3.1'

services:
 jrtb-db:
   image: mysql
   restart: always
   container_name: dev-jrtb-db
   ports:
     - "3306:3306"
   environment:
     MYSQL_DATABASE: "dev_jrtb_db"
     MYSQL_USER: root
     MYSQL_PASSWORD: root
Щоб запустити цей файл для роботи з docker-compose, потрібно використовувати в запиті прапор -f . Це означає, що буде надано ім'я файлу, який запускається, а не взятий стандартний docker-compose.yml. Тому запит буде виглядати так: docker-compose -f docker-compose-test.yml up -d Виходить, спочатку ми говоримо, який взяти файл ( -f docker-compose-test.yml ), а потім говоримо, що потрібно підняти сервіси і зробити це в daemon режимі ( up-d ) - тобто так, щоб процес працював поза сесією терміналу, в якому цю команду запустабо. Запускаємо та пробуємо підключитися до БД, щоб переконатися, що вона піднялася і нею можна користуватися. Для цього відкриваємо знайомий нам MySQL Workbench (ось тут ми говорабо про це ) і створюємо нове з'єднання: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 3Нам потрібно заповнити такі поля:
  • Connection name - ім'я з'єднання - як варіант, DEV_JRTB_DB;
  • Hostname — тут адресаа, на якій розгорнуто БД. У нашому випадку все залишиться, як і було: 127.0.0.1 , ну чи localhost;
  • username – тут буде root, як у нас записано у docker-compose;
  • password - також root.
Після цього необхідно перевірити, чи буде з'єднання. Для цього натискаємо Test Connection : "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 4У результаті отримуємо: Failed to Connect to MySQL… Чому? Заходимо до терміналу і дивимося, що сталося з докер-контейнером. Напишемо в терміналі: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 5Бачимо, що термінал створено 59 хвабон тому, а перезапуск був 55 секунд... чому? Незрозуміло, чи потрібно дивитися логи. Заходимо в терміналі в корінь проекту та запустити наступну команду: docker-compose -f docker-compose-test.yml logs
Отримуємо:

dev-jrtb-db | 2021-02-28 10:14:28+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:28+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:28+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:28+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:29+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:29+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:29+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:30+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:30+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:30+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:30+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:32+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:32+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:32+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:32+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:34+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:34+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:34+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:34+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:37+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:37+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:44+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:44+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:44+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:44+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD dev-jrtb-db | 2021-02-28 10:14:58+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:58+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 10:14:58+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 10:14:58+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified dev-jrtb-db | You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

Тепер зрозуміло, що БД так і не запустилася із нашими налаштуваннями. Помилка одна і та ж, тому вичленуємо її з листа:
2021-02-28 11:03:37+00:00 [ERROR] [Entrypoint]: Database не знижується і password option не specified dev-jrtb-db | Вам потрібна одна з MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
Тобто йому потрібно визначити пароль для root користувача – головного користувача. Добре, зараз ми оновимо наш файл:
version: '3.1'

services:
 jrtb-db:
   image: mysql
   restart: always
   container_name: dev-jrtb-db
   ports:
     - "3306:3306"
   environment:
     MYSQL_DATABASE: "dev_jrtb_db"
     MYSQL_ROOT_PASSWORD: root
Ми прибрали ті змінні за користувача та пароль та додали тільки пароль для рутовского користувача. Це означає, що для користувача root тепер буде пароль root. Принаймні ми так припускаємо. Зараз запустимо і подивимося, що буде: docker-compose -f docker-compose-test.yml up -d І одразу подивимося, що кажуть нам логі: docker-compose -f docker-compose-test.yml logs
Дивимося:

Attaching to dev-jrtb-db dev-jrtb-db | 2021-02-28 11:20:40+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 11:20:41+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' dev-jrtb-db | 2021-02-28 11:20:41+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.23-1debian10 started. dev-jrtb-db | 2021-02-28 11:20:41+00:00 [Note] [Entrypoint]: Initializing database files dev-jrtb-db | 2021-02-28T11:20:41.083803Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.23) initializing of server in progress as process 43 dev-jrtb-db | 2021-02-28T11:20:41.088457Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. dev-jrtb-db | 2021-02-28T11:20:41.447990Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. dev-jrtb-db | 2021-02-28T11:20:42.672093Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option. dev-jrtb-db | 2021-02-28 11:20:45+00:00 [Note] [Entrypoint]: Database files initialized dev-jrtb-db | 2021-02-28 11:20:45+00:00 [Note] [Entrypoint]: Starting temporary server dev-jrtb-db | 2021-02-28T11:20:45.893664Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.23) starting as process 88 dev-jrtb-db | 2021-02-28T11:20:45.921695Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. dev-jrtb-db | 2021-02-28T11:20:46.088339Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. dev-jrtb-db | 2021-02-28T11:20:46.207499Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock dev-jrtb-db | 2021-02-28T11:20:46.369170Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. dev-jrtb-db | 2021-02-28T11:20:46.369357Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. dev-jrtb-db | 2021-02-28T11:20:46.371501Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. dev-jrtb-db | 2021-02-28T11:20:46.402227Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.23' socket: '/var/run/mysqld/mysqld.sock' port: 0 MySQL Community Server - GPL. dev-jrtb-db | 2021-02-28 11:20:46+00:00 [Note] [Entrypoint]: Temporary server started. dev-jrtb-db | Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. dev-jrtb-db | Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it. dev-jrtb-db | Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. dev-jrtb-db | Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it. dev-jrtb-db | 2021-02-28 11:20:49+00:00 [Note] [Entrypoint]: Creating database dev_jrtb_db dev-jrtb-db | dev-jrtb-db | 2021-02-28 11:20:49+00:00 [Note] [Entrypoint]: Stopping temporary server dev-jrtb-db | 2021-02-28T11:20:49.187996Z 11 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.23). dev-jrtb-db | 2021-02-28T11:20:50.925075Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.23) MySQL Community Server - GPL. dev-jrtb-db | 2021-02-28 11:20:51+00:00 [Note] [Entrypoint]: Temporary server stopped dev-jrtb-db | dev-jrtb-db | 2021-02-28 11:20:51+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up. dev-jrtb-db | dev-jrtb-db | 2021-02-28T11:20:51.420058Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.23) starting as process 1 dev-jrtb-db | 2021-02-28T11:20:51.427384Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. dev-jrtb-db | 2021-02-28T11:20:51.577244Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. dev-jrtb-db | 2021-02-28T11:20:51.677659Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock dev-jrtb-db | 2021-02-28T11:20:51.787156Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. dev-jrtb-db | 2021-02-28T11:20:51.787325Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. dev-jrtb-db | 2021-02-28T11:20:51.789742Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. dev-jrtb-db | 2021-02-28T11:20:51.812100Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.23' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.

Помилок начебто вже немає, тому можна дивитися, чи буде доступ. Але, на жаль, доступу знову немає… Нічого: далі розбиратимемося! "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 6Щоб завершити роботу docker-compose та видалити всі контейнери, потрібно написати: docker-compose -f docker-compose-test.yml down Тут ми вказали файл, яким потрібно зробити видалення. Що робити? Будемо гуглити: може, комусь вдалося зробити краще. Найпростіший запит: “example of mysql in docker-compose” допомагає знайти посилання на medium ресурс. Там наводять такий приклад:
version: '3.3'
services:
 db:
   image: mysql:5.7
   restart: always
   environment:
     MYSQL_DATABASE: 'db'
     # So you don't have to use root, but you can if you like
     MYSQL_USER: 'user'
     # You can use whatever password you like
     MYSQL_PASSWORD: 'password'
     # Password for root access
     MYSQL_ROOT_PASSWORD: 'password'
   ports:
     # <Port exposed> : < MySQL Port running inside container>
     - '3306:3306'
   expose:
     # Opens port 3306 on the container
     - '3306'
     # Where our data will be persisted
   volumes:
     - my-db:/var/lib/mysql
# Names our volume
volumes:
 my-db:
Адаптуємо його під наші потреби та отримуємо:
version: '3.1'

services:
 jrtb-db:
   image: mysql:5.7
   restart: always
   environment:
     MYSQL_DATABASE: 'dev_jrtb_db'
     # So you don't have to use root, but you can if you like
     MYSQL_USER: 'dev_jrtb_db_user'
     # You can use whatever password you like
     MYSQL_PASSWORD: 'dev_jrtb_db_password'
     # Password for root access
     MYSQL_ROOT_PASSWORD: 'root'
   ports:
     # <Port exposed> : < MySQL Port running inside container>
     - '3306:3306'
   expose:
       # Opens port 3306 on the container
       - '3306'
Запускаємо цей варіант вже відомою командою: docker-compose -f docker-compose-test.yml up -d Намагаємося ще раз отримати доступ до бази даних через MySQLWorkBench: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 7Нарешті з'явився доступ. Але тепер цікаво, що вплинуло на це. Я грішу на цю частину:
expose:
   # Opens port 3306 on the container
   - '3306'
Перевірити легко: без цього нічого не повинно працювати :D. Перевіримо: видалимо цю частину, перезапустимо docker-compose: docker-compose -f docker-compose-test.yml down docker-compose -f docker-compose-test.yml up Намагаємося зайти в БД через workbench: все зайшло. Тоді єдиний варіант – це версія БД. Тут чітко зазначено 5.7, тобто, якщо поміняти її на останню, не має працювати. Перезапустив — і справді не працює... "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 8Мабуть, якісь проблеми у них з докером на останній версії. Ну гаразд, не біда. Таке часто трапляється із безкоштовним програмним забезпеченням. Будемо використовувати версію 5.7. Подивимося, чи є база даних, яка нам потрібна – dev_jrtb_db. Для цього запустимо Query в MySQL Workbench команду SHOW DATABASES :"Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 9Так, у висновку вона є. Добре, можна рухатися далі. Далі додамо нашу першу міграцію. На основі завдань зі статті "Планування проекту: сім разів відміряй - один раз відріж" створимо нашу першу таблицю tg_user. Всі міграції будуть у папці projectDir/src/main/resources/db/migration , а ім'я буде таке: V00001__add_tg_user_table.sql . Чому саме в тій папці і таке ім'я описував у статті про Spring + flyway. Ось як виглядатиме наша перша міграція: V00001__add_tg_user_table.sql:
-- ensure that the table with this name is removed before creating a new one.
DROP TABLE IF EXISTS tg_user;

-- Create tg_user table
CREATE TABLE tg_user (
   chat_id VARCHAR(100),
   active BOOLEAN
);
Тобто, тут просто ми створюємо таблицю користувача, який має лише ID-шник чату (унікальний елемент, який може бути використаний для роботи як ID у таблиці) та його стан — активний або неактивний. Так, у разі зупинки робота інформація про підписку залишиться, і її можна буде використовувати, якщо роботом знову захочуть скористатися. Іншої інформації про користувача поки що не потрібно. Тепер головне питання: а як це перевірити? Потрібно запустити наш додаток. Поки що в основному файлі docker-compose.yml немає зв'язку з БД, а ще нам потрібно навчитися налагоджувати додаток разом з базою даних. Тому запустимо програму з Intellij IDEA. Для перевірки цього нам потрібно буде запустити наш головний метод у JavarushTelegramBotApplication. Щоб розділити роботу з деплою та тестування, ми будемо використовувати інший файл із пропертями.application-test.properties . За допомогою цього шаблону ми даємо Spring'у зрозуміти, що цей файл використовуватиметься для профілю test . Коли ми не вказуємо профіль, використовується профіль за промовчанням (перевірте це в логах при запуску SpringBoot: у перших рядках про це буде написано). Ось так він виглядатиме:
# MySQL configurations:
spring.datasource.url=jdbc:mysql://localhost:3306/dev_jrtb_db
spring.datasource.username=dev_jrtb_db_user
spring.datasource.password=dev_jrtb_db_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# TelegramBot configurations:
bot.username=tes
bot.token=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
А основний application.properties виглядатиме трохи інакше:
# MySQL configurations:
spring.datasource.url=jdbc:mysql://jrtb-db:3306/jrtb_db
spring.datasource.username=jrtb_db_user
spring.datasource.password=jrtb_db_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# TelegramBot configurations:
bot.username=test.codegym_community_bot
bot.token=1375780501:AAE4A6Rz0BSnIGzeu896OjQnjzsMEG6_uso
Істотна різниця знаходиться в полі spring.datasource.url: у профілі test у нас URL на localhost . Тобто очікується, що програма буде запускатися поза докером, що правда, тому що при налагодженні ми запускатимемо в Intellij IDEA наш проект і чекатимемо, що у нас буде доступ до БД з локальної машини. А ось в application.properties URL вже вказана інша — jrtb-db. Це буде ім'я нашої бази даних у docker-compose, і таким чином наша програма в докері зможе достукатися до бази даних. Чому? Тому вони запустяться в рамках одного docker-compose і знатимуть один про одного таким чином. Це потрібно, щоб ми мали одну закриту інфраструктуру для проекту. Але як запустити профіль під час запуску? Для цього можна налаштувати запуск основного методу в Intellij IDEA. Для цього є Edit Configurations : переходимо в головний клас JavarushTelegramBotApplication, натискаємо на зелену стрілочку навпроти оголошення main методу та вибираємо Modify Run Configuration :"Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 10Вводимо необхідні змінні та налаштовуємо профіль. У Intellij IDEA дещо змінився інтерфейс цього конфігураційного вікна, тому я раджу всім оновити IDEA до останньої версії, щоб ми бачабо однакову картинку: У полі Environment variables нам потрібно додати змінні імені та токена бота за таким шаблоном: ім'я1_переменной= "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 11значення1 ; ім'я2_переменной = . Тобто ключ = значення розділені крапкою з комою. У нашому випадку це буде так: bot.token=1375780501:AAHLzsf4WhcjSdPguDwtggRS1IMu5l8;bot.username=codegym_community_bot (у вас буде інше ім'я та токен для бота ) Далі вибираємо в кнопці Modify options поле Add"Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 12-Dspring.profiles.active=test - це скаже SpringBoot, що потрібно використовувати профіль test, а значить і проперти будуть взяті з application-test.properties. У результаті це буде виглядати так: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 13Тепер запускаємо нашу тестову базу даних: docker-compose -f docker-compose-test.yml up Причому саме так, щоб без приставки -d, щоб у терміналі відразу було видно логи, якщо такі знадобляться. І останній крок – просто запустити main метод. Якщо ви зробите так само, як я описав, в результаті отримаєте: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 14Другим рядком логів буде опис, що запрацював test профіль. Заходимо через MySQLWorkbench і запускаємо дві команди, щоб перевірити, що міграція накотилася і все працює (хоча це і видно з логів запуску програми, але перевірити варто):
  1. use dev_jrtb_db;
  2. show tables;
Результат: "Java-проект від А до Я": Додаємо все, що пов'язане з БД.  Частина 1 - 15Як ми очікували, вийшло дві таблиці. Перша — технічна для обліку міграцій, друга наша таблиця для користувачів Телеграма. Все: Flyway разом з базою даних додано. Тепер нові міграції будуть йти як олією. Найскладніше - це перше налаштування та запуск процесу. Продовжуємо - завершуємо роботу над цим глобальним завданням: додаємо бази даних у docker-compose.yml, додаємо Repository шар, статистику для робота, пишемо та оновлюємо тести та документацію.

Список всіх матеріалів серії на початку цієї статті.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ