Як правильно працювати з MySQL у Java

Всім добрий день! Суть питання: я хочу зрозуміти, чи правильно я побудував схему роботу з MySQL і як правильно закривати з'єднання?

Для спілкування з базою при кожному запиті відкриваю нове з'єднання методом:

далі роблю потрібний запит:

, в якомуfinallyвикликаю метод для закриття всіх поточних з'єднань:

Перше питання:скажіть будь ласка, чи правильно я побудував схему роботу з базою?Друге питання:у мене після кожного запиту в терміналі висить купа Sleep з'єднань:

І в якийсь момент у Java я отримую ось таку помилку:

Що із цим можна зробити?

Дякую. (Скажу відразу я новачок у Java/Back-end/MySQL, довго працював у front-end без Java та MySQL.)

Перше питання: скажіть, будь ласка, чи правильно я побудував схему роботу з базою? Такий підхід має право життя і часто зустрічається у новачків. Але він не дуже зручний у використанні та підтримці.

Друге питання: у мене після кожного запиту в терміналі висить купа Sleep з'єднань Складно сказати в чому справа за тими даними, що ви надали. Можливо, con.close() видав виняток і не закрив з'єднання, а у вас цей виняток тупо ігнорується.

В однопотокових додатках поширена практика відкрити одне з'єднання та працювати з ним весь час, поки програма працює. Тобто приблизно так:

Тобто закривати коннект до бази після кожного запиту необов'язково. У деяких випадках це навіть шкідливо, тому що відкриття нового коннект займає деякий час і при великій кількості запитів цей зверхід стає помітним.

Для багатопотокових програм часто використовується схожа техніка, де кожен поток має свій об'єкт Connection, з яким вінпрацює (наприклад, зберігає свій екземпляр коннекта в ThreadLocal поле).

Але в багатопотокових додатках зручніше користуватися пулом коннектів. Пул бере на себе відповідальність щодо роздачі з'єднань усім стражденним. Він на старті створює відразу кілька з'єднань до бази та зберігає у свою внутрішню колекцію. Далі, у міру необхідності (виклику методу getConnection на пулі), пул видаляє з внутрішньої колекції перший по черзі коннект і повертає його. Якщо колекція порожня, створюється новий коннект і відразу повертається. Основна фішка в тому, що з'єднання, що повертаються цим пулом, при закритті насправді не закриваються, а повертаються назад у внутрішню колекцію пула і можуть бути перевикористані іншими потоками. Таким чином досягається більш висока продуктивність шляхом зменшення кількості відкритих коненктів до бази та збільшення інтенсивності їх використання. Код програми виглядає так, ніби на кожен запит будується нове з'єднання до бази і закривається відразу після завершення роботи з результатом цього запиту.

Зрозуміло, опис у попередньому абзаці досить поверховий і неповний, але описує загальну всім пулів концепцію.

Якщо займатиметеся багатопоточним програмуванням, а це маст хев для backend (особливо, highload), то без пулу коннектів не обійтися. Хоча звичайно можна й обійтися, але в міру розвитку проекту ви пилятимете власну обгортку і в результаті реалізуєте найпростіший пул коннектів. Воно того не варте - простіше відразу взяти готовий.

Я не рекомендую відразу братися за вивчення будь-яких пулів. Спочатку попрактикуйтеся з голим JDBC в однопотокових додатках. Пули коннектів - це вже другий ступінь. До них слід приступати тільки тоді, коли будете впевнено себевідчувати в JDBC. На початковому етапі вони лише заважатимуть.

Коли будете готові освоїти якийсь пул, то раджу звернути увагу на HikariCP. Він давно вже працює у мене в хайлоад проектах і жодного разу не підбивав. Нижче приклад коду з його використанням: