====== 06 - Pool de conexiones ======
Abrir una conexión es caro: negociación de red, autenticación y una sesión reservada en el servidor. Pagar ese precio por cada operación — como hasta ahora — funciona en clase, pero con muchas consultas simultáneas agota la base de datos. Un **pool de conexiones** abre las conexiones **de antemano** y las **reutiliza**.
===== 1. Cómo funciona =====
@startuml
participant "DAO" as dao
participant "Pool" as pool
participant "MariaDB" as db
== Al arrancar ==
pool -> db : crea las conexiones
== En cada operación ==
dao -> pool : getConnection()
pool --> dao : Connection
dao -> db : sentencias
dao -> pool : close()
note over pool : no se cierra: vuelve al pool
@enduml
* ''getConnection()'' **presta** una conexión libre del pool.
* ''close()'' **devuelve** la conexión al pool: no cierra nada de verdad.
* Si el pool está vacío, el que pide espera hasta un máximo; agotarlo de forma constante indica pool corto o conexiones retenidas demasiado tiempo.
===== 2. DataSource =====
JDBC define la interfaz ''javax.sql.DataSource'': una **fábrica de conexiones** que sustituye a ''DriverManager''. Con la librería estándar de facto, **HikariCP**, la clase ''DbConnection'' no cambia de nombre ni de firma; cambia su contenido:
com.zaxxer
HikariCP
5.1.0
public final class DbConnection {
private static final HikariDataSource DATA_SOURCE = buildDataSource();
private static HikariDataSource buildDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(PROPERTIES.getProperty("db.url"));
config.setUsername(PROPERTIES.getProperty("db.user"));
config.setPassword(PROPERTIES.getProperty("db.password"));
config.setMaximumPoolSize(10);
return new HikariDataSource(config); // abre el pool al crearla
}
// misma firma que antes: el DAO ni se entera
public static Connection get() throws SQLException {
return DATA_SOURCE.getConnection();
}
}
^ Ajuste ^ Función ^
| ''maximumPoolSize'' | Conexiones máximas del pool; 10 es un punto de partida razonable |
| ''connectionTimeout'' | Milisegundos de espera al pedir conexión antes de fallar |
El pool se **crea** al arrancar la aplicación y se **cierra** al terminar:
DATA_SOURCE.close(); // apagado de la aplicación, no de cada operación
===== 3. Consecuencias para el código =====
^ Regla ^ Motivo ^
| ''try-with-resources'' en todas las operaciones | ''close'' devuelve la conexión al pool; olvidarla es robarle conexiones al resto |
| Transacciones cortas | Una transacción abierta retiene su conexión; muchas retenciones vacían el pool |
| Misma API | ''Connection'', ''PreparedStatement'' y el resto no cambian: solo cambia de dónde viene la conexión |
Todo el código de los temas anteriores funciona tal cual sobre el pool: el DAO sigue llamando a ''DbConnection.get()'' y cerrando con ''try-with-resources''. Lo único que ha cambiado es el significado de ''close()''.