Konfiguracja połączenia aplikacji Spring Boot z bazą danych PostgreSQL wydaje się na pierwszy rzut oka prosta – kilka właściwości w application.yml i gotowe. W praktyce jednak jakość tej konfiguracji ma bezpośredni wpływ na stabilność, bezpieczeństwo i wydajność systemu, szczególnie w środowiskach produkcyjnych.
Sterownik JDBC i zależności projektu
Spring Boot nie komunikuje się z PostgreSQL bezpośrednio – wykorzystuje sterownik JDBC. Maven:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
Spring Boot:
- automatycznie wykrywa sterownik
- rejestruje DataSource
- integruje go z HikariCP
Częsty błąd w projektach legacy: ręczna konfiguracja DriverManagerDataSource – prowadzi do braku poolingu.
Podstawowa konfiguracja datasource
Najprostsza i jednocześnie poprawna konfiguracja:
spring:
datasource:
url: jdbc:postgresql://localhost:5432/appdb
username: app_user
password: secret
driver-class-name: org.postgresql.Driver
Spring Boot:
- automatycznie tworzy
DataSource - ustawia HikariCP jako
connection pool - udostępnia połączenie dla JPA, JDBC i transakcji
driver-class-name: org.postgresql.Driverjest opcjonalny, Spring wykrywa go sam pojdbc:postgresql:
Składnia URL JDBC
jdbc:postgresql://HOST:PORT/DATABASE
Opcjonalne parametry:
?ssl=true&sslmode=verify-full
Profile środowiskowe (DEV / TEST / PROD)
Poprawna konfiguracja nigdy nie jest jedna dla wszystkich środowisk.Przykład struktury:
- application.yml – wspólne ustawienia
- application-dev.yml
- application-prod.yml
application-prod.yml
spring:
datasource:
url: jdbc:postgresql://prod-db:5432/appdb
username: app_user
password: ${DB_PASSWORD}
Zasada: Hasła nigdy nie są trzymane w repozytorium.
Connection pooling – HikariCP
Spring Boot domyślnie używa HikariCP, który jest:
- szybki
- stabilny
- przewidywalny
Podstawowa konfiguracja HikariCP:
spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
Znaczenie parametrów:
- maximum-pool-size: maksymalna liczba połączeń do PostgreSQL
- max-lifetime: musi być krótszy niż timeout po stronie bazy
- connection-timeout: czas oczekiwania aplikacji na wolne połączenie
Częsty błąd: zwiększanie poola „na ślepo” → przeciążenie PostgreSQL.
Testowanie poprawności połączenia
Spring Boot automatycznie:
- testuje połączenie przy starcie
- przerywa start aplikacji, jeśli baza jest niedostępna
Można wymusić test zapytaniem:
spring:
datasource:
hikari:
connection-test-query: SELECT 1
Dodatkowo warto:
- monitorować pg_stat_activity
- sprawdzać liczbę aktywnych połączeń
- weryfikować timeouty
Bezpieczeństwo połączenia
SSL/TLS
W środowiskach produkcyjnych połączenie powinno być szyfrowane:
spring:
datasource:
url: jdbc:postgresql://db:5432/appdb?ssl=true&sslmode=require
Tryby SSL:
- require
- verify-ca
- verify-full
Użytkownik bazy danych:
Dobra praktyka:
- osobny użytkownik aplikacyjny
- minimalne uprawnienia
- brak SUPERUSER
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
Integracja z JPA i transakcjami
Spring Boot automatycznie:
- łączy
DataSourcezEntityManager - konfiguruje
PlatformTransactionManager
Minimalna konfiguracja JPA:
spring:
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
open-in-view: false
open-in-view=false:
- zapobiega niekontrolowanym zapytaniom
- poprawia przewidywalność transakcji
database-platform: org.hibernate.dialect.PostgreSQLDialect – hibernate od wersji 6 sam rozpoznaje dialekt w locie
Konfiguracja a kontenery (Docker / Kubernetes):
W środowiskach kontenerowych:
- brak localhost
- konfiguracja przez zmienne środowiskowe
Przykład:
spring:
datasource:
url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
username: ${DB_USER}
password: ${DB_PASSWORD}
Zalecane:
- readiness / liveness probes
- opóźniony start aplikacji
- retry logic po stronie infrastruktury
Dodatkowe pomocne opcje:
spring:
datasource:
hikari:
leak-detection-threshold: 2000
Pozwala na wczesne wykrywanie problemów gdy np transakcja nam długo wisi.
Konfiguracja połączenia Spring Boot z PostgreSQL to element architektury, a nie detal techniczny. Dobrze zaprojektowana:
- zapewnia stabilność aplikacji
- chroni bazę danych
- ułatwia skalowanie
- zapobiega problemom produkcyjnym