Очень много приходилось работать со Spring Data Repositories, и проблема с соединениями с БД была не такой уже и редкой. То забудешь сессию закрыть, то что-то пойдет не так и нужный метод не вызывается и поиск ошибок, когда заканчиваются соединения с БД превращаются в настоящую проблему.
Я обычно использую postgresql для продуктива и h2db для тестирования, примеры буду приводить для postgresql.
Вот такой командой можно получить максимальное количество допустимых соединений СУБД. Причем нужно понимать что если у вас на одном сервере несколько бд, то соединения считаются в общем, что нужно учитывать для настройки пулов.
Запрос, которым можно получить число активных соединений.
После очередных изменений стали появляться ошибки.
Не мог понять почему через некоторое время приложение просто падало. Понятно, что заканчиваются соединения в пуле, осталось разобраться из-за чего они заканчиваются.
При настройке источника данных (javax.sql.DataSource) подключение нужно настроить с использованием пула. Пул HikariCP (com.zaxxer.HikariCP) поддерживает механизм поиска connection leak. Для того чтобы его включить, нужно при настройке пула задать таймаут через который пул будет понимать, что соединение зависло и не закрылось.
Значение таймаута задается в миллисекундах. Получилась вот такая конфигурация:
После настройки пула в логе стали появляться исключения
Стектрейс должен привести к методу службы или репозитория где возник leak. Как же я удивился, когда это были обычные методы для чтения.
Дальше вспоминаем, что Stream в отличае от того же List мало того, что может быть прочитан только один раз, так еще и вычисление значения элемента Stream ленивое, то есть выполняется при обращении. В документации spring написано, что обязательно нужно закрывать Stream вручную через вызов метода close или использовать try-with-resources.
В статье по использованию объектов spring-data тоже пишут закрывайте stream. Как это часто бывает, полезная статья вышла уже после того, как ты ошибок понаделал и героически их починил.