Пул соединений

Базовый Java
≈ 2 мин чтения

Создавать физическое соединение на каждый запрос дорого

Открытие соединения с базой включает сетевое взаимодействие, аутентификацию и настройку сессии. Если серверное приложение будет создавать новое физическое соединение для каждого HTTP-запроса, оно потратит много времени и быстро упрётся в лимит подключений базы.

Пул соединений заранее держит ограниченный набор открытых соединений и выдаёт их приложению на короткое время. Когда код вызывает close() у полученного из пула соединения, обычно закрывается не физическое подключение к базе, а логическая обёртка возвращает ресурс обратно в пул.

Приложение обычно работает через DataSource

try (Connection connection = dataSource.getConnection()) {
    try (PreparedStatement statement = connection.prepareStatement(
            "SELECT name FROM users WHERE id = ?")) {
        statement.setLong(1, 42);
        // execute query
    }
}

Интерфейс DataSource даёт приложению точку получения соединений. Сам интерфейс не обязан быть пулом: конкретная реализация может выдавать обычные соединения, а может быть связана с pooling-инфраструктурой. В типичном серверном приложении детали создания и переиспользования соединений скрыты за настроенным DataSource.

Размер пула — это ограничение, а не способ открыть бесконечно много соединений

Если все соединения заняты, следующему запросу приходится ждать освобождения ресурса или завершаться по тайм-ауту. Поэтому утечка одного Connection в приложении с пулом особенно неприятна: со временем доступных соединений становится всё меньше.

Закрывай Connection даже при использовании пула. Именно close() сообщает пулу, что работа закончена и соединение можно выдать следующему запросу. try-with-resources остаётся правильным способом организовать этот жизненный цикл.